package com.yanqu.road.server.manager.activity.hsisland;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.dao.impl.activity.hsisland.*;
import com.yanqu.road.entity.activity.hsisland.*;
import com.yanqu.road.entity.activity.hsisland.config.HsIslandChooseConfig;
import com.yanqu.road.entity.activity.hsisland.config.HsIslandIslandConfig;
import com.yanqu.road.entity.activity.hsisland.config.HsIslandPveConfig;
import com.yanqu.road.entity.activity.hsisland.enums.*;
import com.yanqu.road.entity.enums.eChannelType;
import com.yanqu.road.entity.enums.eChatContentType;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eMessageType;
import com.yanqu.road.entity.log.cross.hsisland.*;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.rank.yrank.UnionYRank;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroupUnion;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.pb.UnionBasePb;
import com.yanqu.road.pb.activity.HsIslandProto;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.ActivityChatMgr;
import com.yanqu.road.server.manager.activity.hsisland.handler.param.HsIslandExploreHandlerReq;
import com.yanqu.road.entity.activity.hsisland.config.HsIslandConfig;
import com.yanqu.road.entity.activity.hsisland.data.*;
import com.yanqu.road.entity.player.CrossUserBaseInfo;
import com.yanqu.road.exception.BusinessException;
import com.yanqu.road.server.manager.activity.ActivityMgr;
import com.yanqu.road.server.manager.activity.hsisland.handler.HsIslandIEventHandler;
import com.yanqu.road.server.manager.activity.hsisland.param.HsIslandBattleOpResult;
import com.yanqu.road.server.manager.activity.hsisland.param.HsIslandPveCheckResult;
import com.yanqu.road.server.manager.activity.hsisland.pb.CrossHsIslandActivityPb;
import com.yanqu.road.server.manager.activity.hsisland.rank.CrossHsIslandRankListModel;
import com.yanqu.road.server.manager.activity.hsisland.rank.HsIslandRank;
import com.yanqu.road.server.manager.activity.hsisland.task.CrossHsIslandNpcActionTask;
import com.yanqu.road.server.manager.log.CrossAutoLogMgr;
import com.yanqu.road.server.manager.npc.CrossNpcUserMgr;
import com.yanqu.road.server.manager.player.WorldMessageMgr;
import com.yanqu.road.server.manager.union.activitygroup.Cross2UnionActivityGroupMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.manager.yrank.CrossYRankMgr;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.*;
import com.yanqu.road.utils.executor.ScheduledThreadPoolHelper;
import com.yanqu.road.utils.plot.PlotUtil;
import com.yanqu.road.utils.plot.Point;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.util.ConcurrentHashSet;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;

import static com.yanqu.road.entity.activity.hsisland.enums.HsIslandBattleFieldEnemyEnum.ENEMY_BOSS;
import static com.yanqu.road.entity.activity.hsisland.enums.HsIslandBattleFieldEnemyEnum.ENEMY_MASTER;
import static com.yanqu.road.server.logic.MessageHelper.sendPacket;
import static com.yanqu.road.server.logic.MessageHelper.sendPacketToAll;

public class CrossHsIslandActivity {

    /**
     * 活动ID
     */
    private int activityId;

    /**
     * 分组ID
     */
    private int groupId;

    /**
     * 平均开服天数
     */
    private int averageOpenDayNum;

    /**
     * 活动锁
     */
    private ReentrantLock lock = new ReentrantLock();

    /**
     * logger
     */
    private static Logger logger = LogManager.getLogger(CrossHsIslandActivity.class.getName());

    /**
     * 活动配置
     */
    private HsIslandConfig config;

    /**
     * 活动数据
     */
    private HsIslandActivityData activityData;

    /**
     * 商会MAP
     */
    private Map<String, CrossHsIslandUnion> unionMap = new ConcurrentHashMap<>();

    /**
     * 玩家MAP
     */
    private Map<Long, CrossHsIslandUser> userMap = new ConcurrentHashMap<>();

    /**
     * 战场伤害map
     */
    private Map<Long, CrossHsIslandBattleFieldDamage> battleFieldDamageMap = new ConcurrentHashMap<>();

    /**
     * boss击杀记录
     */
    private Map<Long, CrossHsIslandKillBossRecord> killBossRecordMap = new ConcurrentHashMap<>();

    /**
     * 战场id
     */
    private AtomicLong maxBattleFieldId = new AtomicLong(1);

    /**
     * 战场数据（纯内存）
     */
    private Map<Long, CrossHsIslandBattleField> battleFieldMap = new ConcurrentHashMap<>();

    private RandomHelper randomHelper = new RandomHelper();


    /**
     * 存储
     */
    public void save() {
        //活动数据存储
        HsIslandActivityDataDaoImpl activityDataDao = new HsIslandActivityDataDaoImpl();
        if (this.activityData.isInsertOption()) {
            activityDataDao.add(this.activityData);
        } else if (this.activityData.isUpdateOption()) {
            activityDataDao.update(this.activityData);
        }
        //玩家数据存储
        HsIslandUserDataDaoImpl userDataDao = new HsIslandUserDataDaoImpl();
        for (CrossHsIslandUser user : this.userMap.values()) {
            if (CrossNpcUserMgr.isNpc(user.getUserData().getUserId())) {
                continue;
            }
            if (user.getUserData().isInsertOption()) {
                userDataDao.add(user.getUserData());
            } else if (user.getUserData().isUpdateOption()) {
                userDataDao.update(user.getUserData());
            }
        }
        //商会数据存储
        for (CrossHsIslandUnion union : this.unionMap.values()) {
            union.save();
        }

        for (CrossHsIslandBattleFieldDamage battleFieldDamage : battleFieldDamageMap.values()) {
            battleFieldDamage.save();
        }

        for (CrossHsIslandKillBossRecord killBossRecord : killBossRecordMap.values()) {
            killBossRecord.save();
        }
    }

    public int getActivityId() {
        return activityId;
    }

    public HsIslandActivityData getActivityData() {
        return activityData;
    }

    public int getGroupId() {
        return groupId;
    }

    public HsIslandConfig getConfig() {
        return config;
    }

    /**
     * 构造函数
     * @param config
     * @param groupId
     */
    public CrossHsIslandActivity(HsIslandConfig config, int groupId) {
        this.activityId = config.getActivityInfo().getActivityId();
        this.config = config;
        this.groupId = groupId;
        //重载数据
        this.reloadData();
        // 初始化一些数据
        this.initData();
    }

    /**
     * 重载数据
     */
    private void reloadData() {
        //活动数据
        HsIslandActivityDataDaoImpl activityDataDao = new HsIslandActivityDataDaoImpl();
        this.activityData = activityDataDao.getHsIslandActivityData(this.activityId, this.groupId);
        if (this.activityData == null) {
            this.activityData = new HsIslandActivityData(this.activityId, this.groupId);
        }
        //玩家数据
        HsIslandUserDataDaoImpl userDataDao = new HsIslandUserDataDaoImpl();
        //读取玩家数据
        Map<Long, HsIslandUserData> userDataMap = userDataDao.getHsIslandUserMap(this.activityId, this.groupId);
        Map<String, Map<Long, CrossHsIslandUser>> unionsUserMap = new ConcurrentHashMap<>();//商会玩家MAP
        Map<String, Map<Integer, Map<Long, CrossHsIslandUser>>> unionFloorUserMap = new ConcurrentHashMap<>();//商会海域玩家MAP
        for (HsIslandUserData userData : userDataMap.values()) {
            //个人日志长度
            int logLimit = this.getConfig().HSISLAND_PERSON_RECORD_LIMIT;
            //构造user数据
            CrossHsIslandUser user = new CrossHsIslandUser(userData, logLimit);
            this.userMap.put(user.getUserData().getUserId(), user);
            //商会玩家MAP
            Map<Long, CrossHsIslandUser> unionUserMap = unionsUserMap.computeIfAbsent(userData.getUnionId(), (k) -> new ConcurrentHashMap<>());
            unionUserMap.put(user.getUserData().getUserId(), user);
            //商会海域玩家MAP
            Map<Integer, Map<Long, CrossHsIslandUser>> floorUserMap = unionFloorUserMap.computeIfAbsent(userData.getUnionId(), (k) -> new ConcurrentHashMap<>());
            Map<Long, CrossHsIslandUser> fUserMap = floorUserMap.computeIfAbsent(userData.getFloorId(), (k) -> new ConcurrentHashMap<>());
            fUserMap.put(user.getUserData().getUserId(), user);
        }

        //商会数据
        HsIslandUnionDataDaoImpl unionDataDao = new HsIslandUnionDataDaoImpl();
        HsIslandFloorDataDaoImpl floorDataDao = new HsIslandFloorDataDaoImpl();
        HsIslandIslandDataDaoImpl islandDataDao = new HsIslandIslandDataDaoImpl();
        HsIslandEventDataDaoImpl eventDataDao = new HsIslandEventDataDaoImpl();
        //读取商会数据
        Map<String, HsIslandUnionData> unionDataMap = unionDataDao.getHsIslandUnionMap(this.activityId, this.groupId);
        for (HsIslandUnionData unionData : unionDataMap.values()) {
            Map<Integer, CrossHsIslandFloor> floorMap = new ConcurrentHashMap<>();
            Map<Integer, Map<Long, CrossHsIslandUser>> floorUserMap = unionFloorUserMap.get(unionData.getUnionId());
            //读取海域数据
            Map<Integer, HsIslandFloorData> floorDataMap = floorDataDao.getHsIslandFloorMap(this.activityId, this.groupId, unionData.getUnionId());
            for (HsIslandFloorData floorData : floorDataMap.values()) {
                Map<Integer, CrossHsIslandIsland> islandMap = new ConcurrentHashMap<>();
                //读取岛屿数据
                Map<Integer, HsIslandIslandData> islandDataMap = islandDataDao.getHsIslandIslandMap(this.activityId, this.groupId, unionData.getUnionId(), floorData.getFloorId());
                for (HsIslandIslandData islandData : islandDataMap.values()) {
                    //读取事件数据
                    Map<String, HsIslandEventData> eventDataMap = eventDataDao.getHsIslandEventMap(this.activityId, this.groupId, unionData.getUnionId(), floorData.getFloorId(), islandData.getIslandId());
                    Map<String, HsIslandEventData> notFinishEventMap = new ConcurrentHashMap<>();//未完结位置
                    Set<String> finishPositionSet = new ConcurrentHashSet<>();//已完成位置
                    for (Map.Entry<String, HsIslandEventData> entry : eventDataMap.entrySet()) {
                        String key = entry.getKey();
                        HsIslandEventData eventData = entry.getValue();
                        if (eventData.getFinishFlag() == HsIslandFinishFlagEnum.FINISH_NOT.getType()) {
                            //未完结
                            notFinishEventMap.put(key, eventData);
                        } else {
                            //已完结（未领取奖励的PVE事件，领取完奖励才移除）
                            if (eventData.getEventId() == HsIslandEventIdEnum.EVENT_PVE.getType() || eventData.getEventId() == HsIslandEventIdEnum.EVENT_PVE_BIG.getType()) {
                                if (eventData.getRewardFlag() == HsIslandYnFlagEnum.NOT.getType()) {
                                    notFinishEventMap.put(key, eventData);
                                    //玩家未领取pv奖励数量(玩家海域的才算)
                                    CrossHsIslandUser user = this.userMap.get(eventData.getUserId());
                                    if (user != null && user.getUserData().getFloorId() == eventData.getFloorId()) {
                                        user.addPveRewardNum(1);
                                    }
                                }
                            }
                            finishPositionSet.add(key);
                        }
                    }
                    //获取事件类型数量MAP
                    Map<Integer, Integer> eventNumMap = eventDataDao.getEventTypeNumMap(this.activityId, this.groupId, unionData.getUnionId(), floorData.getFloorId(), islandData.getIslandId());
                    //构造岛屿数据
                    CrossHsIslandIsland island = new CrossHsIslandIsland(islandData, notFinishEventMap, finishPositionSet, eventNumMap);
                    islandMap.put(island.getIslandData().getIslandId(), island);
                }
                //海域玩家MAP
                Map<Long, CrossHsIslandUser> fUserMap = floorUserMap.getOrDefault(floorData.getFloorId(), new ConcurrentHashMap<>());
                //构造floor数据
                CrossHsIslandFloor floor = new CrossHsIslandFloor(floorData, islandMap, fUserMap);
                floorMap.put(floor.getFloorData().getFloorId(), floor);
            }
            //商会玩家数据
            Map<Long, CrossHsIslandUser> unionUserMap = unionsUserMap.getOrDefault(unionData.getUnionId(), new ConcurrentHashMap<>());
            //构造union数据
            int logLimit = this.getConfig().HSISLAND_GUILD_RECORD_LIMIT;
            CrossHsIslandUnion union = new CrossHsIslandUnion(unionData, floorMap, unionUserMap, logLimit);
            this.unionMap.put(union.getUnionData().getUnionId(), union);

            // boss伤害榜单加载出来吧，这边不加载普通怪的伤害了
            HsIslandBattleFieldDamageDataDaoImpl battleFieldDamageDataDao = new HsIslandBattleFieldDamageDataDaoImpl();
            for (Integer bossId : this.config.HSISLAND_HOLY_PILLARS_BOSS_ORDER) {
                // 获取boss的所有战场id
                List<Long> bossBattleFieldIdList = battleFieldDamageDataDao.getAllBattleFieldByMonsterId(activityId, groupId, bossId);
                for (Long bossBattleFieldId : bossBattleFieldIdList) {
                    CrossHsIslandBattleFieldDamage data = new CrossHsIslandBattleFieldDamage(activityId, groupId, bossBattleFieldId, bossId, ENEMY_BOSS);
                    battleFieldDamageMap.put(data.getBattleFieldId(), data);
                }
            }

            // 拉一下boss击杀记录
            HsIslandKillBossRecordDaoImpl killBossRecordDao = new HsIslandKillBossRecordDaoImpl();
            Map<Long, HsIslandKillBossRecord> hsIslandKillBossRecordMap = killBossRecordDao.getHsIslandKillBossRecordMap(activityId, groupId);
            for (HsIslandKillBossRecord killBossRecord : hsIslandKillBossRecordMap.values()) {
                killBossRecordMap.put(killBossRecord.getBattleFieldId(), new CrossHsIslandKillBossRecord(killBossRecord));
            }
        }
    }

    /**
     * 刷新配置
     * @param config
     */
    public void refreshConfig(HsIslandConfig config) {
        this.config = config;
    }

    /**
     * 初始化数据
     */
    private void initData() {
        // 最大的战场id
        this.maxBattleFieldId = new AtomicLong(System.currentTimeMillis() / 1000);
        //获取区服列表
        List<Long> serverList = this.config.getActivityInfo().getServerIdList();
        // 平均开服天数
        this.averageOpenDayNum = ServerListMgr.getAverageOpenDayNum(serverList, DateHelper.getTodayZeroTime());
        // 锁定一下战意值
        if (activityData.getMaxBattleValue() == 0) {
            for (List<Long> _progress : this.config.HSISLAND_HOLY_PILLARS_BOSS_NEED_PROGRESS) {
                if (this.averageOpenDayNum >= _progress.get(0)) {
                    activityData.setMaxBattleValue(_progress.get(1));
                }
            }
            if (activityData.getMaxBattleValue() == 0) {
                logger.error("未找到合适的战意值上限,activityId:{},groupId:{}", this.activityId, this.groupId);
            }
        }
    }

    /**
     * 获取商会
     * @param unionId
     * @return
     */
    public CrossHsIslandUnion getUnion(String unionId) {
        return this.unionMap.get(unionId);
    }

    /**
     * 初始化商会
     * @param unionId
     * @return
     */
    public synchronized CrossHsIslandUnion initUnion(String unionId) throws BusinessException {
        CrossHsIslandUnion union = this.unionMap.get(unionId);
        if (union == null) {
            //双被捐献次数
            int doubleDonateNum = this.config.HSISLAND_INITIAL_DOUBLE_DONATE_NUM;
            //商会数据
            HsIslandUnionData unionData = new HsIslandUnionData(this.activityId, this.groupId, unionId, doubleDonateNum, doubleDonateNum);
            //海域MAP
            Map<Integer, CrossHsIslandFloor> floorMap = new ConcurrentHashMap<>();
            //玩家MAP
            Map<Long, CrossHsIslandUser> userMap = new ConcurrentHashMap<>();
            //日志长度
            int logLimit = this.getConfig().HSISLAND_GUILD_RECORD_LIMIT;
            //实例化商会对象
            union = new CrossHsIslandUnion(unionData, floorMap, userMap, logLimit);
            this.unionMap.put(unionId, union);
            //初始海域
            union.createFloor();
        }
        return union;
    }

    /**
     * 获取玩家MAP
     * @param userId
     * @return
     */
    public CrossHsIslandUser getUser(long userId) {
        return this.userMap.get(userId);
    }

    /**
     * 获取商会MAP
     * @return
     */
    public Map<String, CrossHsIslandUnion> getUnionMap() {
        return unionMap;
    }

    /**
     * 初始化玩家
     * @param userId
     * @return
     */
    public synchronized CrossHsIslandUser initUser(long userId, CrossHsIslandUnion union, List<HsIslandPatronsData> patronsList) throws BusinessException {
        CrossHsIslandUser user = this.userMap.get(userId);
        if (user == null) {
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
            //初始形象ID
            int imageId = this.config.HSISLAND_INITIAL_DOLL_ID;
            //初始体力
            int energy = this.config.HSISLAND_INITIAL_ENERGY;
            //初始层，默认商会最高层
            int floorId = union.getUnionData().getMaxFloorId();
            CrossHsIslandFloor floor = union.getFloor(floorId);
            if (floor == null) {
                floor = union.createFloor();
            }
            //初始协助次数
            int helpNum = this.config.HSISLAND_PVE_INITIAL_ASSIST_TIMES;
            //初始pve可被邀请次数
            int canPveInviteNum = this.config.HSISLAND_PVE_INITIAL_INVITE_TIMES;
            // 初始精力
            int initPvpEnergy = this.getConfig().getMaxPvpEnergy(floorId);
            //前30战力门客
            Map<Integer, HsIslandPatronsData> patronsMap = new ConcurrentHashMap<>();
            for (HsIslandPatronsData patron : patronsList) {
                if (patronsMap.size() >= this.config.HSISLAND_POWER_PATRONS_NUM) {
                    break;
                }
                patronsMap.put(patron.getPatronsId(), patron);
            }
            //双被捐献次数
            int doubleDonateNum = this.config.HSISLAND_INITIAL_DOUBLE_DONATE_NUM;
            HsIslandUserData userData = new HsIslandUserData(
                    this.activityId,
                    this.groupId,
                    userId,
                    userBaseInfo.getServerId(),
                    union.getUnionData().getUnionId(),
                    imageId,
                    energy,
                    floorId,
                    0,
                    0,
                    0,
                    helpNum,
                    canPveInviteNum,
                    patronsMap,
                    initPvpEnergy,
                    doubleDonateNum
            );
            //个人日志长度
            int logLimit = this.getConfig().HSISLAND_PERSON_RECORD_LIMIT;
            user = new CrossHsIslandUser(userData, logLimit);
            this.userMap.put(userId, user);
            //商会注入玩家
            union.putUser(user);
            //海域注入玩家
            floor.putUser(user);
        }
        return user;
    }

    /**
     * 同步玩家数据
     * @param userId
     */
    public void syncUserData(long userId) {
        CrossHsIslandUser user = this.userMap.get(userId);
        if (user != null) {
            user.syncUserData();
        }
    }

    /**
     * 同步玩家红点
     * @param userId
     */
    public void syncUserRedDot(long userId) {
        CrossHsIslandUser user = this.userMap.get(userId);
        if (user != null) {
            user.syncRedDot();
        }
    }

    /**
     * 活动结束-更新区服商会成就定时任务
     */
    public synchronized void updateUnionAcEndActivity() {
        if (this.activityData.getUpdateUnionAcTime() > 0) {
            return;
        }
        //判断活动是否结束
        long now = System.currentTimeMillis();
        if (now > this.config.getActivityInfo().getEndTime() * 1000) {
            logger.info("海神岛-活动结束-更新区服商会成就定时任务-start");
            //设置一下，处理时间
            this.activityData.setUpdateUnionAcTime(System.currentTimeMillis());
            //更新区服商会成就定时任务（为保证活动期间未登录玩家【商会成就】【基金分】最新）
            for (CrossHsIslandUnion union : this.unionMap.values()) {
                //更新商会成就分，基金分
                HsIslandProto.HsIslandUnionScoreChangeEndActivityFromCrossMsg.Builder msg = HsIslandProto.HsIslandUnionScoreChangeEndActivityFromCrossMsg.newBuilder();
                msg.setActivityId(this.activityId);
                msg.setMaxFloorId(union.getUnionData().getMaxFloorId());
                msg.setMaxFloodProgress(String.valueOf(union.getMaxFloorExploreProgress()));
                msg.setUnionScore(union.getUnionScore());
                MessageHelper.sendPacketToAll(Protocol.S_HS_ISLAND_END_UNION_SCORE_CHANGE_FROM_CROSS, msg, union.getUserMap().keySet(), true);
            }
            logger.info("海神岛-活动结束-更新区服商会成就定时任务-end");
        }
    }

    /**
     * 通知区服商会成就变更
     * @param userId
     */
    public void syncUserChangeUnionAchievement(long userId) {
        CrossHsIslandUser user = this.userMap.get(userId);
        if (user != null) {
            CrossHsIslandUnion union = unionMap.get(user.getUserData().getUnionId());
            if (union != null) {
                HsIslandProto.HsIslandConditionChangeFromCrossMsg.Builder msg = HsIslandProto.HsIslandConditionChangeFromCrossMsg.newBuilder();
                msg.setActivityId(this.activityId);
                msg.setConditionType(eGamePlayerEventType.HsIslandUnionAchievement.getValue());
                msg.setValue(union.getUnionData().getMaxFloorId());
                msg.setParam(String.valueOf(union.getMaxFloorExploreProgress()));
                MessageHelper.sendPacket(user.getUserData().getServerId(), user.getUserData().getUserId(), YanQuMessageUtils.buildMessage(Protocol.S_HS_ISLAND_CONDITION_CHANGE_FROM_CROSS, msg));
            }
        }
    }

    /**
     * 通知区服基金分变更
     * @param userId
     */
    public void syncUserChangeFundScore(long userId) {
        CrossHsIslandUser user = this.userMap.get(userId);
        if (user != null) {
            CrossHsIslandUnion union = unionMap.get(user.getUserData().getUnionId());
            if (union != null) {
                HsIslandProto.HsIslandConditionChangeFromCrossMsg.Builder msg = HsIslandProto.HsIslandConditionChangeFromCrossMsg.newBuilder();
                msg.setActivityId(this.activityId);
                msg.setConditionType(eGamePlayerEventType.CommonActivityFundProgress.getValue());
                msg.setValue(union.getUnionScore());
                msg.setParam("");
                MessageHelper.sendPacket(user.getUserData().getServerId(), user.getUserData().getUserId(), YanQuMessageUtils.buildMessage(Protocol.S_HS_ISLAND_CONDITION_CHANGE_FROM_CROSS, msg));
            }
        }
    }

    /**
     * 通用检查
     * @param userId
     * @param checkInTime
     * @param checkInDailyBattleTime
     * @throws BusinessException
     */
    public void commonCheck(long userId, boolean checkInTime, boolean checkInDailyBattleTime) throws BusinessException {
        //判断活动是否在展示期
        if (!ActivityMgr.activityInShowTime(this.config.getActivityInfo())) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ACTIVITY_NOT_IN_SHOW_TIME);
        }
        //判断活动是否在活动期
        if (checkInTime && !this.config.checkInActivityTime()) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ACTIVITY_NOT_IN_TIME);
        }
        //判断是否在每天活动进行期
        if (checkInDailyBattleTime && !this.config.checkInDailyBattleTime()) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ACTIVITY_NOT_IN_DAILY_BATTLE_TIME);
        }
        //判断玩家是否在名单内
        if (userId > 0 && !CrossNpcUserMgr.isNpc(userId)) {
            UnionActivityGroupUnion unionData = Cross2UnionActivityGroupMgr.getUnionData(this.config.getActivityInfo().getActivityId(), userId);
            if (unionData == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_NOT_IN_LIST);
            }
        }
    }

    /**
     * 创建PVE血量
     * @param monsterId
     * @return
     */
    public HsIslandMonsterData createPveMonster(int monsterId) {
        long allBlood;
        HsIslandPveConfig monsterConfig = this.config.getPveConfig(monsterId);
        if (monsterConfig.getType() == HsIslandMonsterTypeEnum.BOSS.getType()) {
            // boss
            allBlood = calcBossBlood();
        } else {
            //普通怪物,大型怪
            allBlood = monsterConfig.getMonsterBlood(this.averageOpenDayNum);
        }
        return new HsIslandMonsterData(monsterId, allBlood, maxBattleFieldId.incrementAndGet());
    }

    /**
     * 计算boss血量
     *
     * @return boss的血量
     */
    private long calcBossBlood() {
        // 所有玩家
        List<CrossHsIslandUser> userList = new ArrayList<>(userMap.values());
        // 根据魂力排序一下(降序)
        userList.sort(Comparator.comparingLong(CrossHsIslandUser::getPower).reversed());

        BigDecimal bossBlood = BigDecimal.ZERO;
        int totalPlayers = userList.size();

        // 确保配置参数的长度一致
        if (this.config.HSISLAND_HOLY_PILLARS_BOSS_POWER_PARAM_1.size() != this.config.HSISLAND_HOLY_PILLARS_BOSS_POWER_PARAM_2.size()) {
            throw new IllegalArgumentException("配置参数长度不一致");
        }

        for (int i = 0; i < this.config.HSISLAND_HOLY_PILLARS_BOSS_POWER_PARAM_1.size(); i++) {
            BigDecimal percentage = new BigDecimal(this.config.HSISLAND_HOLY_PILLARS_BOSS_POWER_PARAM_1.get(i));
            BigDecimal coefficient = new BigDecimal(this.config.HSISLAND_HOLY_PILLARS_BOSS_POWER_PARAM_2.get(i));

            // 计算当前区间的起始和结束排名
            int startRank = (i == 0) ? 0 : new BigDecimal(this.config.HSISLAND_HOLY_PILLARS_BOSS_POWER_PARAM_1.get(i - 1))
                    .divide(BigDecimal.valueOf(1000), 10, RoundingMode.UP)
                    .multiply(new BigDecimal(totalPlayers))
                    .setScale(0, RoundingMode.UP)
                    .intValueExact();

            int endRank = percentage
                    .divide(BigDecimal.valueOf(1000), 10, RoundingMode.UP)
                    .multiply(new BigDecimal(totalPlayers))
                    .setScale(0, RoundingMode.UP)
                    .intValueExact();

            // 遍历该区间的玩家，并计算他们对boss血量的贡献
            for (int j = startRank; j < endRank && j < totalPlayers; j++) {
                CrossHsIslandUser user = userList.get(j);
                BigDecimal userPower = new BigDecimal(user.getPower());
                BigDecimal contribution = userPower.multiply(coefficient).divide(BigDecimal.valueOf(1000), RoundingMode.UP);
                bossBlood = bossBlood.add(contribution);
            }
        }
        return bossBlood.setScale(0, RoundingMode.UP).longValueExact();
    }


    /**
     * 获取随机PVP商会
     * @param unionId
     * @return
     */
    public CrossHsIslandUnion getRandomPvpUnion(String unionId) {
        //前start，后end
        int start = this.config.HSISLAND_PVP_RANGE.get(0);
        int end = this.config.HSISLAND_PVP_RANGE.get(1);
        List<UnionYRank> rankList = CrossYRankMgr.getSortUnionRankList(this.activityId, this.groupId, String.valueOf(eGamePlayerEventType.HsIslandUnionRank.getValue()));
        int rank = CrossYRankMgr.getUnionRankNum(rankList, unionId);
        if (rank <= 0) {
            return null;
        }
        List<UnionYRank> newRankList = ListHelper.getSubListWithoutIndex(rankList, rank - 1, start, end);
        //判断一下，商户人数是否满足 >=5
        int minUserNum = this.config.HSISLAND_PVP_FAULT_TOLERANT;
        Set<CrossHsIslandUnion> pvpUnionSet = new HashSet<>();
        for (UnionYRank unionYRank : newRankList) {
            //获取商会人数
            CrossHsIslandUnion union = this.unionMap.get(unionYRank.getUnionUid());
            if (union != null && !Objects.equals(union.getUnionData().getUnionId(), unionId) && union.getUserMap().size() >= minUserNum) {
                pvpUnionSet.add(union);
            }
        }
        //如果以上的商会集合还是空的，从所有的商会中取出符合的
        if (pvpUnionSet.isEmpty()) {
            for (CrossHsIslandUnion union : this.unionMap.values()) {
                if (union != null && !Objects.equals(union.getUnionData().getUnionId(), unionId) && union.getUserMap().size() >= minUserNum) {
                    pvpUnionSet.add(union);
                }
            }
        }
        //从 pvpUnionSet 中随机出一个商会
        return RandomHelper.getRandomElement(pvpUnionSet);
    }

    /**
     * 创建事件
     * @param userId
     * @param floor
     * @param island
     * @param x
     * @param y
     * @param checkLink 是否检测连通
     * @param pointEventId 指定事件ID
     * @return
     * @throws BusinessException
     */
    public HsIslandEventData createEvent(long userId, CrossHsIslandFloor floor, CrossHsIslandIsland island, int x, int y, boolean checkLink, int pointEventId, int lightFlag) throws BusinessException {
        //获取岛屿配置
        HsIslandIslandConfig islandConfig = this.getConfig().getIslandConfig(island.getIslandData().getIslandId());
        if (islandConfig == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_FOUND);
        }
        //判断坐标是否合法
        if (!islandConfig.checkPositionCanExplore(x, y)) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_POSITION_TYPE_NOT_EXPLORE);
        }
        //判断坐标是否已经有事件
        boolean hasEvent = island.checkPositionHasEvent(x, y);
        if (hasEvent) {
            floor.syncLaChangeForUser(userId, island.getIslandData().getIslandId(), x, y);
            //同步一下地块数据
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_POSITION_HAS_EVENT);
        }
        //判断是否连通
        boolean linkFlag = island.checkPositionLink(x, y);
        if (checkLink && !linkFlag) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_POSITION_NOT_LINK);
        }
        //获取事件ID
        int eventId = this.getWeightRandomEventId(floor, island, x, y, pointEventId);
        return new HsIslandEventData(
                this.activityId,
                this.groupId,
                floor.getFloorData().getUnionId(),
                floor.getFloorData().getFloorId(),
                island.getIslandData().getIslandId(),
                userId,
                floor.getUnEventIdAndIncrement(),
                eventId,
                lightFlag
        );
    }

    /**
     * 获取权重随机出的事件ID
     * @param floor
     * @param island
     * @param x
     * @param y
     * @return
     */
    public int getWeightRandomEventId(CrossHsIslandFloor floor, CrossHsIslandIsland island, int x, int y, int pointEventId) throws BusinessException {
        String key = x + "_" + y;
        //特殊：判断是否是宝箱
        if (island.getIslandData().getIslandId() == floor.getFloorData().getBoxIslandId()) {
            HsIslandBoxData boxData = floor.getFloorData().getBoxDataMap().get(key);
            if (boxData != null) {
                //判断宝库是否已经被发现
                if (floor.getFloorData().getBoxFindUserId() > 0) {
                    throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BOX_ALREADY_FIND);
                }
                return HsIslandEventIdEnum.EVENT_BOX.getType();
            }
        }
        //特殊：判断是是否是4格pve事件
        if (island.getIslandData().getFourLaPositions().containsKey(key)) {
            //判断事件是否已经被发现
            if (island.checkPositionHasEvent(x, y)) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_POSITION_HAS_EVENT);
            }
            return HsIslandEventIdEnum.EVENT_PVE_BIG.getType();
        }
        //特殊：判断是否必出海神之心。探索进度达到
        if (island.checkMustShowKey()) {
            return HsIslandEventIdEnum.EVENT_KEY.getType();
        }
        //特殊：判断是否必出海神之心。1.只剩5个格子 && 2.没有海神之心
        int canExploreNum = floor.getCanExploreLaNum(island.getIslandData().getIslandId());
        if (canExploreNum <= 5 && island.getIslandData().getKeyNum() <= 0) {
            return HsIslandEventIdEnum.EVENT_KEY.getType();
        }
        //岛屿配置
        HsIslandIslandConfig islandConfig = this.getConfig().getIslandConfig(island.getIslandData().getIslandId());
        //事件权重MAP
        Map<Integer, Integer> eventWeightMap = new HashMap<>(islandConfig.getLatticeWeightMap());
        //移除大型PVE事件和宝库事件
        eventWeightMap.remove(HsIslandEventIdEnum.EVENT_PVE_BIG.getType());
        eventWeightMap.remove(HsIslandEventIdEnum.EVENT_BOX.getType());
        //移除事件次数达上限的事件
        Map<Integer, Integer> eventNumMap = islandConfig.getLatticeParamMap();
        for (Map.Entry<Integer, Integer> entry : eventNumMap.entrySet()) {
            int eventId = entry.getKey();
            int eventMaxNum = entry.getValue();
            //已拥有的事件数量
            int num = island.getEventNum(eventId);
            if (num >= eventMaxNum) {
                //达上限，移除
                eventWeightMap.remove(eventId);
            }
        }
        //PVP事件是否满足
        CrossHsIslandUnion pvpUnion = this.getRandomPvpUnion(floor.getFloorData().getUnionId());
        if (pvpUnion == null) {
            eventWeightMap.remove(HsIslandEventIdEnum.EVENT_PVP.getType());
        }
        //判断是否达到出海神之心的条件
        boolean canExploreKey = island.checkCanExploreKey();
        if (!canExploreKey) {
            eventWeightMap.remove(HsIslandEventIdEnum.EVENT_KEY.getType());
        } else {
            //可出海神之心，根据探索进度，增加权重
            Integer keyWeight = eventWeightMap.get(HsIslandEventIdEnum.EVENT_KEY.getType());
            if (keyWeight != null) {
                int keyAddWeight = island.getExploreKeyWeight();
                if (keyAddWeight > 0) {
                    eventWeightMap.put(HsIslandEventIdEnum.EVENT_KEY.getType(), keyWeight + keyAddWeight);
                }
            }
        }
        //判断是否是测试渠道,返回指定事件ID
        int channelId = ConfigHelper.getInt("channelId");
        if (eChannelType.isInnerTestChannel(channelId) && pointEventId > 0 && eventWeightMap.containsKey(pointEventId)) {
            return pointEventId;
        }
        //权重随机事件ID
        if (!eventWeightMap.isEmpty()) {
            return RandomHelper.getRandomKeyByWeight(eventWeightMap);
        } else {
            //没有事件的情况下，保底给小pve事件
            return HsIslandEventIdEnum.EVENT_PVE.getType();
        }
    }

    /**
     * 解锁形象，补发积分
     * @param userId
     */
    public void unlockImageBfScore(long userId) throws BusinessException {
        CrossHsIslandUser user = this.userMap.get(userId);
        if (user == null) {
            //玩家信息
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
            if (userBaseInfo == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_BASE_NOT_FOUND);
            }
//            //判断玩家是否有商会
//            String unionId = userBaseInfo.getUnionUid();
            //获取商会
            String unionId = Cross2UnionActivityGroupMgr.getUnionUid(this.activityId, userId);
            if (StringUtils.isNullOrEmpty(unionId)) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_UNION);
            }
            //判断商会数据是否存在
            CrossHsIslandUnion union = this.getUnion(unionId);
            if (union == null) {
                //初始化商会
                union = this.initUnion(unionId);
            }
            //初始化玩家
            user = this.initUser(userId, union, new ArrayList<>());
        }
        //解锁
        user.unlockImageBfScore();
    }

    /**
     * 推送跑马灯-boss
     * @param marqueeTypeEnum
     * @param bossId
     */
    public void syncMarqueeBossMsg(HsIslandMarqueeTypeEnum marqueeTypeEnum, int bossId) {
        HsIslandProto.HsIslandSyncMarqueeMsg.Builder msg = HsIslandProto.HsIslandSyncMarqueeMsg.newBuilder();
        msg.setType(marqueeTypeEnum.getType());
        msg.setBossId(bossId);
        MessageHelper.sendPacketToAll(Protocol.U_HS_ISLAND_SYNC_MARQUEE, msg, this.userMap.keySet());
    }

    /**
     * pve-日志
     * @param user
     * @param union
     * @param result
     * @param eventData
     * @param reward
     */
    public void addPveLog(CrossHsIslandUser user, CrossHsIslandUnion union, HsIslandBattleResult result, HsIslandEventData eventData, HsIslandReward reward) {
        //个人日志
        HsIslandUserLog userLog = new HsIslandUserLog();
        userLog.setType(result.isWinFlag() ? HsIslandUserLogTypeEnum.USER_LOG_TYPE_1.getType() : HsIslandUserLogTypeEnum.USER_LOG_TYPE_2.getType());
        userLog.setPveMonsterId(eventData.getMonsterData().getMonsterId());
        userLog.setReward(reward);
        userLog.setValue(result.getDamage());
        userLog.setTime(System.currentTimeMillis());
        user.addUserLog(userLog);
        //商会日志
        if (result.isWinFlag()) {
            if (eventData.getEventId() == HsIslandEventIdEnum.EVENT_PVE_BIG.getType()) {
                HsIslandUnionLog unionLog = new HsIslandUnionLog();
                if (user.getUserData().getUserId() == eventData.getUserId()) {
                    unionLog.setType(HsIslandUnionLogTypeEnum.UNION_LOG_TYPE_1.getType());
                } else {
                    unionLog.setType(HsIslandUnionLogTypeEnum.UNION_LOG_TYPE_2.getType());
                    unionLog.setHelpUserId(eventData.getUserId());
                }
                unionLog.setUserId(user.getUserData().getUserId());
                unionLog.setPveMonsterId(eventData.getMonsterData().getMonsterId());
                unionLog.setReward(reward);
                unionLog.setTime(System.currentTimeMillis());
                union.addUnionLog(unionLog);
            }
        }
    }

    /*********************************交互协议*************************************/

    /**
     * 进入活动
     * @param userId
     * @param patronsList
     * @throws BusinessException
     */
    public void enterActivity(long userId, List<HsIslandPatronsData> patronsList) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //玩家信息
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if (userBaseInfo == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_BASE_NOT_FOUND);
        }
        //获取商会
        String unionId = Cross2UnionActivityGroupMgr.getUnionUid(this.activityId, userId);
//        //判断玩家是否有商会
//        String unionId = userBaseInfo.getUnionUid();
        if (StringUtils.isNullOrEmpty(unionId)) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_UNION);
        }
        //判断商会数据是否存在
        CrossHsIslandUnion union = this.getUnion(unionId);
        if (union == null) {
            //初始化商会
            union = this.initUnion(unionId);
        }
        //获取玩家数据
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            user = this.initUser(userId, union, patronsList);
            //商会成就更新
            this.syncUserChangeUnionAchievement(userId);
            //基金分更新
            this.syncUserChangeFundScore(userId);
        } else {
            //判断门客数据是否存在
            if (user.getUserData().getPatronsMap() == null || user.getUserData().getPatronsMap().isEmpty()) {
                //前30战力门客
                Map<Integer, HsIslandPatronsData> patronsMap = new ConcurrentHashMap<>();
                for (HsIslandPatronsData patron : patronsList) {
                    if (patronsMap.size() >= this.config.HSISLAND_POWER_PATRONS_NUM) {
                        break;
                    }
                    patronsMap.put(patron.getPatronsId(), patron);
                }
                user.getUserData().setPatronsMap(patronsMap);
            }
        }
        //更新战力
        user.updatePower(patronsList);
        //更新活跃时间
        user.updateActiveTime();
        //同步下海域玩家，我的位置
        CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
        floor.syncUserChangePosition(user);
        //恢复下体力
        user.energyRestore();
    }

    /**
     * 进入下一个海域
     * @param userId
     * @throws BusinessException
     */
    public void enterFloor(long userId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        try {
            //加锁-商会，设置5秒超时
            if (!union.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("海神岛-进入海域-加锁-超时：{}, {}, {}", userId);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            //获取当前海域
            CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
            if (floor == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
            }
            //判断岛屿是否存在
            if (floor.getIslandMap().isEmpty()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_FOUND);
            }
            //判断海神之心是否集齐
            if (floor.getKeyNum() < 3) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_KEY_NOT_ENOUGH);
            }
            //判断海域ID是否合法
            if (floor.getFloorData().getFloorId() >= union.getUnionData().getMaxFloorId()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_MAX_FLOOR);
            }
            //获取目标海域
            CrossHsIslandFloor targetFloor = union.getFloor(union.getUnionData().getMaxFloorId());
            if (targetFloor == null) {
                //创建海域
                targetFloor = union.createFloor();
                //商会日志-商会有人首次到达新海域
                HsIslandUnionLog unionLog = new HsIslandUnionLog();
                unionLog.setType(HsIslandUnionLogTypeEnum.UNION_LOG_TYPE_5.getType());
                unionLog.setUserId(user.getUserData().getUserId());
                unionLog.setFloor(floor.getFloorData().getFloorId());
                unionLog.setKeyNum(floor.getKeyNum());
                unionLog.setTime(System.currentTimeMillis());
                union.addUnionLog(unionLog);
            }
            //玩家离开当前海域
            floor.removeUser(user);
            //玩家进入目标海域
            targetFloor.putUser(user);
            //清空未领取奖励数量
            int pveRewardNum = user.getPveRewardNum();
            if (pveRewardNum > 0) {
                user.addPveRewardNum(-pveRewardNum);
            }
        } catch (InterruptedException e) {
            logger.error("海神岛-进入海域-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            union.getLock().unlock();
        }
    }

    /**
     * 移动
     * @param userId
     * @param islandId
     * @param x
     * @param y
     * @throws BusinessException
     */
    public void move(long userId, int islandId, int x, int y) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        try {
            //加锁-商会，设置5秒超时
            if (!union.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("海神岛-移动-加锁-超时：{}, {}, {}", userId, x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            //获取海域
            CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
            if (floor == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
            }
            //校验是否可通行
            floor.checkPositionCanMove(islandId, x, y);
            //玩家位置变更
            user.changePosition(islandId, x, y);
        } catch (InterruptedException e) {
            logger.error("海神岛-移动-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            union.getLock().unlock();
        }
    }

    /**
     * 探索
     * @param userId
     * @param x
     * @param y
     * @param pointEventId 指定事件ID,调试使用
     * @return
     * @throws BusinessException
     */
    public HsIslandExploreResult explore(long userId, int x, int y, int pointEventId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        try {
            //加锁-商会，设置5秒超时
            if (!union.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("海神岛-探索-加锁-超时：{}, {}, {}", userId, x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            //获取海域
            CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
            if (floor == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
            }
            //获取岛屿
            CrossHsIslandIsland island = floor.getIsland(user.getUserData().getIslandId());
            if (island == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_FOUND);
            }
            //探索
            return this.exploreOne(user, union, floor, island, x, y, pointEventId);
        } catch (InterruptedException e) {
            logger.error("海神岛-探索-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            union.getLock().unlock();
        }
    }

    /**
     * 批量探索
     * @param userId
     * @param positions
     * @return
     * @throws BusinessException
     */
    public List<HsIslandExploreResult> exploreBatch(long userId, List<HsIslandProto.HsIslandUserPositionData> positions) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        try {
            //加锁-商会，设置5秒超时
            if (!union.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("海神岛-探索-加锁-超时：{}, {}, {}", userId);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            //获取海域
            CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
            if (floor == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
            }
            //获取岛屿
            CrossHsIslandIsland island = floor.getIsland(user.getUserData().getIslandId());
            if (island == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_FOUND);
            }
            //判断是否解锁了批量探索
            if (!user.getUserData().getUnlockedImageIds().contains(HsIslandImageIdEnum.IMAGE_ADD_SCORE.getType())) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BATCH_EXPLORE_NOT_UNLOCK);
            }
            //判断批量探索的格子是个9宫格
            List<Point> pointList = new ArrayList<>();
            for (HsIslandProto.HsIslandUserPositionData position : positions) {
                pointList.add(new Point(position.getX(), position.getY()));
            }
            boolean isSquareGrid = PlotUtil.isSquareGrid(pointList, this.config.HSISLAND_FAST_FUNCTION_LATTICE_PARAM);
            if (!isSquareGrid) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_NOT_SQUARE_GRID);
            }
            //探索
            List<HsIslandExploreResult> list = new ArrayList<>();
            for (HsIslandProto.HsIslandUserPositionData position : positions) {
                try {
                    HsIslandExploreResult exploreResult = this.exploreOne(user, union, floor, island, position.getX(), position.getY(), 0);
                    list.add(exploreResult);
                } catch (BusinessException e) {
                    logger.info("海神岛-批量探索失败：{},{},{},{},{},{}", e.getCode(), userId, floor.getFloorData().getFloorId(), island.getIslandData().getIslandId(), position.getX(), position.getY());
                }
            }
            return list;
        } catch (InterruptedException e) {
            logger.error("海神岛-探索-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            union.getLock().unlock();
        }
    }

    /**
     * 探索一次
     * @param user
     * @param union
     * @param floor
     * @param island
     * @param x
     * @param y
     * @param pointEventId
     * @return
     * @throws BusinessException
     */
    public HsIslandExploreResult exploreOne(CrossHsIslandUser user, CrossHsIslandUnion union, CrossHsIslandFloor floor, CrossHsIslandIsland island, int x, int y, int pointEventId) throws BusinessException {
        //判断体力是否足够
        boolean energyFlag = user.checkExploreEnergyEnough();
        if (!energyFlag) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ENERGY_NOT_ENOUGH);
        }
        //生成事件
        HsIslandEventData eventData = this.createEvent(user.getUserData().getUserId(), floor, island, x, y, true, pointEventId, HsIslandYnFlagEnum.NOT.getType());
        //消耗体力
        HsIslandCostEnergyResult energyResult = user.exploreReduceEnergy();
        if (!energyResult.isSuccessFlag()) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ENERGY_NOT_ENOUGH);
        }
        //消耗buff次数，挂载在事件上
        user.eventAddBuff(eventData);
        //根据事件ID进行相应的处理
        HsIslandIEventHandler eventHandler = CrossHsIslandActivityMgr.getEventHandler(eventData.getEventId());
        HsIslandExploreHandlerReq req = new HsIslandExploreHandlerReq();
        req.setActivity(this);
        req.setUser(user);
        req.setUnion(union);
        req.setFloor(floor);
        req.setIsland(island);
        req.setEventData(eventData);
        req.setX(x);
        req.setY(y);
        //返回
        HsIslandExploreResult resp = eventHandler.explore(req);
        //添加积分
        if (resp.getReward() != null) {
            user.addScore(resp.getReward().getScore());
        }
        //商会榜单变更
        if (floor.getFloorData().getFloorId() == union.getUnionData().getMaxFloorId()) {
            union.unionRankChange();
        }
        //连通check
        for (HsIslandEventData item : resp.getEventDataList()) {
            for (HsIslandPosition position : item.getPositions()) {
                island.checkLightPositionsLink(position.getX(), position.getY());
            }
        }
        //同步地块数据变更
        floor.syncLaChange(user.getUserData().getIslandId(), resp.getEventDataList(), false);
        //更新活跃时间
        user.updateActiveTime();
        //探索日志
        LogCrossHsIslandExplore log = new LogCrossHsIslandExplore(
                this.activityData.getActivityId(),
                this.activityData.getGroupId(),
                user.getUserData().getUnionId(),
                user.getUserData().getUserId(),
                floor.getFloorData().getFloorId(),
                island.getIslandData().getIslandId(),
                energyResult.getCostEnergy(),
                x + "," + y,
                eventData.getEventId(),
                resp.getReward() != null ? resp.getReward().getScore() : 0,
                resp.getReward() != null ? PropertyHelper.parsePropertyToString(resp.getReward().getReward()) : "",
                island.getLightProgress(),
                island.getExploreProgress()
        );
        CrossAutoLogMgr.add(log);
        return resp;
    }

    /**
     * pvp
     * @param userId
     * @param x
     * @param y
     * @return
     * @throws BusinessException
     */
    public HsIslandPvpBattleResult pvp(long userId, int islandId, int x, int y) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        try {
            //加锁-商会，设置5秒超时
            if (!union.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("海神岛-PVP-加锁-超时：{}, {}, {}", userId, x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            //获取海域
            CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
            if (floor == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
            }
            //获取岛屿
            CrossHsIslandIsland island;
            if (islandId > 0) {
                island = floor.getIsland(islandId);
            } else {
                island = floor.getIsland(user.getUserData().getIslandId());
            }
            if (island == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_FOUND);
            }
            //判断事件是否完结
            if (island.checkPositionFinish(x, y)) {
                //同步一下地块信息
                floor.syncLaChangeForUser(userId, island.getIslandData().getIslandId(), x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_FINISHED);
            }
            //获取事件
            HsIslandEventData event = island.getEvent(x, y);
            if (event == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_FOUND);
            }
            //判断事件是PVP事件
            if (event.getEventId() != HsIslandEventIdEnum.EVENT_PVP.getType()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_TYPE_ERROR);
            }
            //判断事件是否属于自己
            if (event.getUserId() != userId) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_ME);
            }
            //判断pvp数据是否正确
            if (StringUtils.isNullOrEmpty(event.getPvpUnionId()) || event.getPvpUserIds().isEmpty()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_PVP_EVENT_INFO_ERROR);
            }
            //对方商会是否存在
            CrossHsIslandUnion targetUnion = this.unionMap.get(event.getPvpUnionId());
            if (targetUnion == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_TARGET_UNION_NOT_FOUND);
            }
            List<CrossHsIslandUser> pvpUserList = new ArrayList<>();
            for (long pvpUserId : event.getPvpUserIds()) {
                CrossHsIslandUser pvpUser = this.userMap.get(pvpUserId);
                if (pvpUser != null) {
                    pvpUserList.add(pvpUser);
                }
            }
            //战斗前的buff
            String buffStr = user.getBuffStr();
            //战斗
            HsIslandPvpBattleResult result = user.pvp(pvpUserList, event);
            //添加积分
            user.addScore(result.getHsIslandReward().getScore());
            //事件完结
            island.finishEvent(event);
            result.setEventData(event);
            //同步地块数据变更
            floor.syncLaChange(user.getUserData().getIslandId(), event, false);
            //个人日志-魂师连战事件
            HsIslandUserLog userLog = new HsIslandUserLog();
            userLog.setType(result.getWinNum() == 0 ? HsIslandUserLogTypeEnum.USER_LOG_TYPE_4.getType() : HsIslandUserLogTypeEnum.USER_LOG_TYPE_3.getType());
            userLog.setReward(result.getHsIslandReward());
            userLog.setValue(result.getWinNum() );
            userLog.setTargetUnionName(targetUnion.getBaseUnionInfo() != null ? targetUnion.getBaseUnionInfo().getUnionName() : "");//获取对方玩家所在公会名称
            userLog.setTime(System.currentTimeMillis());
            user.addUserLog(userLog);
            //日志
            Property allReward = new Property();
            allReward.addProperty(result.getHsIslandReward().getReward());
            allReward.addProperty(result.getHsIslandReward().getMoreWinReward());
            LogCrossHsIslandPvp log = new LogCrossHsIslandPvp(
                    user.getUserData().getActivityId(),
                    user.getUserData().getGroupId(),
                    user.getUserData().getUnionId(),
                    user.getUserData().getUserId(),
                    targetUnion.getUnionData().getUnionId(),
                    StringUtils.listToString(event.getPvpUserIds(), ","),
                    union.getPowerAddRate(),
                    buffStr,
                    result.getWinNum(),
                    result.getHsIslandReward().getScore(),
                    PropertyHelper.parsePropertyToString(allReward)
            );
            CrossAutoLogMgr.add(log);
            return result;
        } catch (InterruptedException e) {
            logger.error("海神岛-PVP-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            union.getLock().unlock();
        }
    }

    /**
     * 处理事件-2选1
     * @param userId
     * @param x
     * @param y
     * @param index
     * @return
     * @throws BusinessException
     */
    public HsIslandChooseResult doChooseEvent(long userId, int islandId, int x, int y, int index) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        try {
            //加锁-商会，设置5秒超时
            if (!union.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("海神岛-2选1操作-加锁-超时：{}, {}, {}", userId, x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            //获取海域
            CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
            if (floor == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
            }
            //获取岛屿
            CrossHsIslandIsland island;
            if (islandId > 0) {
                island = floor.getIsland(islandId);
            } else {
                island = floor.getIsland(user.getUserData().getIslandId());
            }
            if (island == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_FOUND);
            }
            //判断事件是否完结
            if (island.checkPositionFinish(x, y)) {
                //同步一下地块信息
                floor.syncLaChangeForUser(userId, island.getIslandData().getIslandId(), x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_FINISHED);
            }
            //获取事件
            HsIslandEventData event = island.getEvent(x, y);
            if (event == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_FOUND);
            }
            //判断事件是类型是否正确
            if (event.getEventId() != HsIslandEventIdEnum.EVENT_CHOOSE.getType()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_TYPE_ERROR);
            }
            //判断下标是否正确
            if (index != 0 && index != 1) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_CHOOSE_EVENT_INDEX_ERROR);
            }
            //判断2选1配置ID是否正确
            if (event.getChooseConfigId() <= 0) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_CHOOSE_ID_ERROR);
            }
            //判断事件是否属于自己
            if (event.getUserId() != userId) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_ME);
            }
            //获取配置
            HsIslandChooseConfig chooseConfig = this.getConfig().getChooseConfig(event.getChooseConfigId());
            if (chooseConfig == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_CHOOSE_CONFIG_NOT_FOUND);
            }
            //2选1
            HsIslandReward rewardData = user.doChoose(event, index);
            //添加积分
            user.addScore(rewardData.getScore());
            //事件完结
            island.finishEvent(event);
            //同步地块数据变更
            floor.syncLaChange(island.getIslandData().getIslandId(), event, false);
            //日志
            LogCrossHsIslandChoose log = new LogCrossHsIslandChoose(
                    user.getUserData().getActivityId(),
                    user.getUserData().getGroupId(),
                    user.getUserData().getUnionId(),
                    user.getUserData().getUserId(),
                    floor.getFloorData().getFloorId(),
                    user.getUserData().getIslandId(),
                    index,
                    chooseConfig.getTypeByIndex(index),
                    PropertyHelper.parsePropertyToString(rewardData.getReward())
            );
            CrossAutoLogMgr.add(log);
            //返回
            HsIslandChooseResult result = new HsIslandChooseResult();
            HsIslandEventReward hsIslandEventReward = new HsIslandEventReward();
            hsIslandEventReward.setEventData(event);
            hsIslandEventReward.setReward(rewardData);
            result.setHsIslandEventReward(hsIslandEventReward);
            result.setChooseConfigId(chooseConfig.getId());
            result.setIndex(index);
            int type = chooseConfig.getTypeByIndex(index);
            result.setChooseTrue(type >= 1);
            return result;
        } catch (InterruptedException e) {
            logger.error("海神岛-2选1操作-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            union.getLock().unlock();
        }
    }

    /**
     * 事件处理-遗迹藏宝
     * @param userId
     * @param x
     * @param y
     * @param index
     * @return
     * @throws BusinessException
     */
    public HsIslandEventReward doRelicEvent(long userId, int islandId, int x, int y, int index) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        try {
            //加锁-商会，设置5秒超时
            if (!union.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("海神岛-遗迹藏宝操作-加锁-超时：{}, {}, {}", userId, x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            //获取海域
            CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
            if (floor == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
            }
            //获取岛屿
            CrossHsIslandIsland island;
            if (islandId > 0) {
                island = floor.getIsland(islandId);
            } else {
                island = floor.getIsland(user.getUserData().getIslandId());
            }
            if (island == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_FOUND);
            }
            //判断事件是否完结
            if (island.checkPositionFinish(x, y)) {
                //同步一下地块信息
                floor.syncLaChangeForUser(userId, island.getIslandData().getIslandId(), x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_FINISHED);
            }
            //获取事件
            HsIslandEventData event = island.getEvent(x, y);
            if (event == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_FOUND);
            }
            //判断事件是类型是否正确
            if (event.getEventId() != HsIslandEventIdEnum.EVENT_RELIC.getType()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_TYPE_ERROR);
            }
            //判断事件是否属于自己
            if (event.getUserId() != userId) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_ME);
            }
            //判断index是否合法
            if (index >= 3 || index < -1) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_RELIC_INDEX_ERROR);
            }
            //判断是否是放弃
            if (index == -1) {
                //事件完结
                island.finishEvent(event);
                HsIslandEventReward result = new HsIslandEventReward();
                result.setEventData(event);
                return result;
            }
            //判断下标是否选择过
            int selectNum = 0;
            for (HsIslandReceiveRelicRewardData rewardData : event.getReceiveRelicRewardMap().values()) {
                if (rewardData.getIndex() == index) {
                    throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_RELIC_INDEX_RECEIVED);
                }
                if (rewardData.getReceiveFlag() == HsIslandYnFlagEnum.YES.getType()) {
                    selectNum++;
                }
            }
            //消耗体力
            int costEnergy = this.config.HSISLAND_RELIC_CONSUME.get(selectNum);
            boolean reduceEnergyFlag = user.reduceEnergy(costEnergy, HsIslandLogEnergyTypeEnum.COST_RELIC);
            if (!reduceEnergyFlag) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ENERGY_NOT_ENOUGH);
            }
            //遗迹藏宝
            HsIslandReward rewardData = user.doRelic(event, index);
            //添加积分
            user.addScore(rewardData.getScore());
            //事件完结,已没有可选择的奖励
            if (event.getNotSelectRelicReward() <= 0) {
                island.finishEvent(event);
            }
            //同步地块数据变更
            floor.syncLaChange(island.getIslandData().getIslandId(), event, false);
            //日志
            LogCrossHsIslandRelic log = new LogCrossHsIslandRelic(
                    user.getUserData().getActivityId(),
                    user.getUserData().getGroupId(),
                    user.getUserData().getUnionId(),
                    userId,
                    floor.getFloorData().getFloorId(),
                    costEnergy,
                    PropertyHelper.parsePropertyToString(rewardData.getReward())
            );
            CrossAutoLogMgr.add(log);
            //返回
            HsIslandEventReward result = new HsIslandEventReward();
            result.setEventData(event);
            result.setReward(rewardData);
            return result;
        } catch (InterruptedException e) {
            logger.error("海神岛-遗迹藏宝操作-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            union.getLock().unlock();
        }
    }

    /**
     * 开启宝箱
     * @param userId
     * @param x
     * @param y
     * @return
     * @throws BusinessException
     */
    public HsIslandEventReward doOpenBox(long userId, int islandId, int x, int y) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        try {
            //加锁-商会，设置5秒超时
            if (!union.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("海神岛-开宝箱操作-加锁-超时：{}, {}, {}", userId, x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            //获取海域
            CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
            if (floor == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
            }
            //获取岛屿
            CrossHsIslandIsland island;
            if (islandId > 0) {
                island = floor.getIsland(islandId);
            } else {
                island = floor.getIsland(user.getUserData().getIslandId());
            }
            if (island == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_FOUND);
            }
            //判断事件是否完结
            if (island.checkPositionFinish(x, y)) {
                //同步一下地块信息
                floor.syncLaChangeForUser(userId, island.getIslandData().getIslandId(), x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_FINISHED);
            }
            //获取事件
            HsIslandEventData event = island.getEvent(x, y);
            if (event == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_FOUND);
            }
            //判断事件是类型是否正确
            if (event.getEventId() != HsIslandEventIdEnum.EVENT_BOX.getType()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_TYPE_ERROR);
            }
            //判断岛屿是否有宝箱
            if (floor.getFloorData().getBoxIslandId() != island.getIslandData().getIslandId()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_NOT);
            }
            //打开宝箱
            HsIslandReward rewardResult = floor.openBox(user, x, y, island);
            //返回
            HsIslandEventReward result = new HsIslandEventReward();
            result.setEventData(event);
            result.setReward(rewardResult);
            return result;
        } catch (InterruptedException e) {
            logger.error("海神岛-开宝箱操作-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            union.getLock().unlock();
        }
    }

    /**
     * 事件处理-明灯
     * @param userId
     * @param islandId
     * @param x
     * @param y
     * @param positions
     * @return
     * @throws BusinessException
     */
    public HsIslandLightResult doLight(long userId, int islandId, int x, int y, List<HsIslandProto.HsIslandUserPositionData> positions) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        try {
            //加锁-商会，设置5秒超时
            if (!union.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("海神岛-明灯操作-加锁-超时：{}, {}, {}", userId, x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            //获取海域
            CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
            if (floor == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
            }
            //获取岛屿
            CrossHsIslandIsland island = floor.getIsland(user.getUserData().getIslandId());
            if (island == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_FOUND);
            }
            //判断事件是否完结
            if (island.checkPositionFinish(x, y)) {
                //同步一下地块信息
                floor.syncLaChangeForUser(userId, island.getIslandData().getIslandId(), x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_FINISHED);
            }
            //获取事件
            HsIslandEventData event = island.getEvent(x, y);
            if (event == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_FOUND);
            }
            //判断事件是类型是否正确
            if (event.getEventId() != HsIslandEventIdEnum.EVENT_LIGHT.getType()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_TYPE_ERROR);
            }
            //判断事件是否属于自己
            if (event.getUserId() != userId) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_ME);
            }
            //探明岛屿是否存在
            CrossHsIslandIsland lightIsland = floor.getIsland(islandId);
            if (lightIsland == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_LIGHT_ISLAND_NOT_FOUND);
            }
            //判断是否是5格
            if (positions.size() > 5) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_NOT_SQUARE_GRID);
            }
            //判断是否是五个格组
            List<Point> pointList = new ArrayList<>();
            for (HsIslandProto.HsIslandUserPositionData position : positions) {
                pointList.add(new Point(position.getX(), position.getY()));
            }
            boolean isFivePoints = PlotUtil.isFivePoints(pointList);
            if (!isFivePoints) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_NOT_SQUARE_GRID);
            }
            //探明
            List<HsIslandExploreResult> exploreResultList = new ArrayList<>();
            for (HsIslandProto.HsIslandUserPositionData position : positions) {
                try {
                    //生成事件
                    HsIslandEventData eventData = this.createEvent(userId, floor, lightIsland, position.getX(), position.getY(), false, 0, HsIslandYnFlagEnum.YES.getType());
                    //根据事件ID进行相应的处理
                    HsIslandIEventHandler eventHandler = CrossHsIslandActivityMgr.getEventHandler(eventData.getEventId());
                    HsIslandExploreHandlerReq req = new HsIslandExploreHandlerReq();
                    req.setActivity(this);
                    req.setUser(user);
                    req.setUnion(union);
                    req.setFloor(floor);
                    req.setIsland(lightIsland);
                    req.setEventData(eventData);
                    req.setX(position.getX());
                    req.setY(position.getY());
                    //返回
                    HsIslandExploreResult exploreResult = eventHandler.explore(req);
                    //添加积分
                    if (exploreResult.getReward() != null) {
                        user.addScore(exploreResult.getReward().getScore());
                    }
                    exploreResultList.add(exploreResult);
                    //探索日志
                    LogCrossHsIslandExplore log = new LogCrossHsIslandExplore(
                            this.activityData.getActivityId(),
                            this.activityData.getGroupId(),
                            user.getUserData().getUnionId(),
                            userId,
                            floor.getFloorData().getFloorId(),
                            lightIsland.getIslandData().getIslandId(),
                            0,
                            position.getX() + "," + position.getY(),
                            eventData.getEventId(),
                            exploreResult.getReward() != null ? exploreResult.getReward().getScore() : 0,
                            exploreResult.getReward() != null ? PropertyHelper.parsePropertyToString(exploreResult.getReward().getReward()) : "",
                            lightIsland.getLightProgress(),
                            lightIsland.getExploreProgress()
                    );
                    CrossAutoLogMgr.add(log);
                } catch (BusinessException e) {
                    logger.info("海神岛-明灯操作-不可生成事件：{}，{}，{}，{}", e.getCode(), island.getIslandData().getIslandId(), position.getX(), position.getY());
                }
            }
            //在岛屿记录下明灯开启的坐标块
            lightIsland.addLightPositions(exploreResultList);
            //完结事件
            island.finishEvent(event);
            //同步地块数据变更
            floor.syncLaChange(island.getIslandData().getIslandId(), event, false);
            //返回
            HsIslandLightResult result = new HsIslandLightResult();
            result.setEventData(event);
            result.setExploreResultList(exploreResultList);
            return result;
        } catch (InterruptedException e) {
            logger.error("海神岛-明灯操作-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            union.getLock().unlock();
        }
    }

    /**
     * 商会情报-日志
     * @param userId
     * @return
     * @throws BusinessException
     */
    public Map<Integer, HsIslandEventData> getHelpEventLogMap(long userId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        //获取海域
        CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
        if (floor == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
        }
        Map<Integer, HsIslandEventData> eventDataMap = new HashMap<>();
        for (CrossHsIslandIsland island : floor.getIslandMap().values()) {
            for (HsIslandEventData eventData : island.getEventMap().values()) {
                //PVE事件
                if (eventData.getEventId() == HsIslandEventIdEnum.EVENT_PVE.getType()
                        || eventData.getEventId() == HsIslandEventIdEnum.EVENT_PVE_BIG.getType()) {
                    //未完结
                    if (eventData.getFinishFlag() == HsIslandFinishFlagEnum.FINISH_NOT.getType()) {
                        eventDataMap.put(eventData.getEventUnId(), eventData);
                        continue;
                    }
                    //已完结 && 奖励未领取 && 属于自己的
                    if (eventData.getFinishFlag() == HsIslandFinishFlagEnum.FINISH_YES.getType()
                            && eventData.getRewardFlag() == HsIslandYnFlagEnum.NOT.getType()
                            && eventData.getUserId() == userId) {
                        eventDataMap.put(eventData.getEventUnId(), eventData);
                    }
                }
            }
        }
        return eventDataMap;
    }

    /**
     * 商会情报-海神宝库
     * @param userId
     * @return
     * @throws BusinessException
     */
    public List<HsIslandFloorBoxData> getFloorBoxList(long userId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        List<HsIslandFloorBoxData> floorBoxList = new ArrayList<>();
        for (CrossHsIslandFloor floor : union.getFloorMap().values()) {
            if (user.getUserData().getFloorId() >= floor.getFloorData().getFloorId()) {
                HsIslandFloorBoxData floorBoxData = new HsIslandFloorBoxData();
                floorBoxData.setFloorId(floor.getFloorData().getFloorId());
                floorBoxData.setAllNum(floor.getFloorData().getBoxFindUserId() > 0 ? floor.getBoxAllNum() : 0);
                floorBoxData.setResidueNum(floor.getBoxAllNum() - floor.getBoxReceivedNum());
                floorBoxData.setMyAllNum(floor.getBoxUserAllNum(userId));
                floorBoxData.setMyReceivedNum(floor.getBoxUserReceivedNum(userId));
                //领取记录
                for (HsIslandBoxData boxData : floor.getFloorData().getBoxDataMap().values()) {
                    if (boxData.getUserId() > 0) {
                        HsIslandFloorBoxReceive floorBoxReceive = new HsIslandFloorBoxReceive();
                        floorBoxReceive.setUserId(boxData.getUserId());
                        floorBoxReceive.setReward(boxData.getReward());
                        floorBoxData.addReceive(floorBoxReceive);
                    }
                }
                floorBoxList.add(floorBoxData);
            }
        }
        return floorBoxList;
    }

    /**
     * 领取商会情报-日志奖励
     * @param userId
     * @param islandId
     * @param x
     * @param y
     * @return
     * @throws BusinessException
     */
    public HsIslandReward receiveHelpLogReward(long userId, int islandId, int x, int y) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        try {
            //加锁-商会，设置5秒超时
            if (!union.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("海神岛-领取商会情报log奖励-加锁-超时：{}, {}, {}", userId, x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            //获取海域
            CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
            if (floor == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
            }
            //获取岛屿
            CrossHsIslandIsland island = floor.getIsland(islandId);
            if (island == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_FOUND);
            }
            //获取事件
            HsIslandEventData event = island.getEvent(x, y);
            if (event == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_FOUND);
            }
            //判断事件是类型是否正确
            if (event.getEventId() != HsIslandEventIdEnum.EVENT_PVE.getType() && event.getEventId() != HsIslandEventIdEnum.EVENT_PVE_BIG.getType()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_TYPE_ERROR);
            }
            //判断事件是否完结
            if (event.getFinishFlag() == HsIslandFinishFlagEnum.FINISH_NOT.getType()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_FINISHED);
            }
            //奖励是否已经领取
            if (event.getRewardFlag() == HsIslandYnFlagEnum.YES.getType()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REWARD_RECEIVED);
            }
            //判断怪物数据是否存在
            if (event.getMonsterData() == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_MONSTER_NOT_FOUND);
            }
            //怪配置
            HsIslandPveConfig pveConfig = this.config.getPveConfig(event.getMonsterData().getMonsterId());
            Property reward = PropertyHelper.parseNewStringToProperty(pveConfig.getReward());
            //设置奖励已经领取
            event.setRewardFlag(HsIslandYnFlagEnum.YES.getType());
            //玩家未领取奖励计数-1
            user.addPveRewardNum(-1);
            //移除事件事件
            island.removeEvent(event);
            //奖励
            return user.createReward(0, reward, null, event);
        } catch (InterruptedException e) {
            logger.error("海神岛-领取商会情报log奖励-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            union.getLock().unlock();
        }
    }

    /**
     * 一键开启宝箱
     * @param userId
     * @param floorId
     * @return
     * @throws BusinessException
     */
    public HsIslandReward receiveFloorBoxReward(long userId, int floorId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        try {
            //加锁-商会，设置5秒超时
            if (!union.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("海神岛-领取商会情报log奖励-加锁-超时：{}, {}", userId, floorId);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            //获取海域
            CrossHsIslandFloor floor = union.getFloor(floorId);
            if (floor == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
            }
            //判断宝库是否被发现
            if (floor.getFloorData().getBoxFindUserId() <= 0) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BOX_NOT_FOUND);
            }
            //一键开启宝箱
            List<HsIslandReward> rewardList = floor.oneKeyOpenBox(user, union);
            HsIslandReward reward = new HsIslandReward();
            for (HsIslandReward hsIslandReward : rewardList) {
                reward.getReward().addProperty(hsIslandReward.getReward());
            }
            return reward;
        } catch (InterruptedException e) {
            logger.error("海神岛-领取商会情报log奖励-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            union.getLock().unlock();
        }
    }

    /**
     * 解锁打理形象
     * @param userId
     * @throws BusinessException
     */
    public void unlockAutoImage(long userId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //解锁打理形象
        user.unlockAutoImage();
    }

    /**
     * 使用形象
     * @param userId
     * @param imageId
     * @throws BusinessException
     */
    public void useImage(long userId, int imageId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        user.useImage(imageId);
    }

    /**
     * 捐献
     * @param userId
     * @param propNum
     * @return
     * @throws BusinessException
     */
    public String donate(long userId, int propNum) throws BusinessException {
        //通用检测
        this.commonCheck(userId, false, false);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        try {
            //加锁-商会，设置5秒超时
            if (!union.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("海神岛-捐献-加锁-超时：{}, {}", userId, propNum);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            return union.donate(user, propNum);
        } catch (InterruptedException e) {
            logger.error("海神岛-捐献-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            union.getLock().unlock();
        }
    }

    /**
     * 使用道具恢复体力
     * @param userId
     * @param propNum
     * @throws BusinessException
     */
    public void usePropRecoverEnergy(long userId, int propNum) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        user.usePropRecoverEnergy(propNum);
    }

    /**
     * 获取商会成员MAP
     * @param userId
     * @return
     * @throws BusinessException
     */
    public Map<Long, CrossHsIslandUser> getUnionUserMap(long userId, List<Long> userIds) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        return this.getUnionUserMap(user.getUserData().getUnionId(), userIds);
    }

    /**
     * 获取商会成列表
     * @param unionId
     * @param userIds
     * @return
     * @throws BusinessException
     */
    public Map<Long, CrossHsIslandUser> getUnionUserMap(String unionId, List<Long> userIds) throws BusinessException{
        //获取商会
        CrossHsIslandUnion union = this.getUnion(unionId);
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        //玩家MAP
        Map<Long, CrossHsIslandUser> userMap = union.getUserMap();
        Map<Long, CrossHsIslandUser> resultMap = new HashMap<>();
        if (userIds != null && !userIds.isEmpty()) {
            for (long queryUserId : userIds) {
                CrossHsIslandUser queryUser = userMap.get(queryUserId);
                if (queryUser != null) {
                    resultMap.put(queryUserId, queryUser);
                }
            }
        } else {
            resultMap = userMap;
        }
        return resultMap;
    }

    /**
     * 获取打理奖励
     * @param userId
     * @return
     * @throws BusinessException
     */
    public Property getAutoReward(long userId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        return user.getAutoReward();
    }

    /**
     * 清空打理奖励
     * @param userId
     * @return
     * @throws BusinessException
     */
    public void clearAutoReward(long userId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        user.clearAutoReward();
    }

    /**
     * 获取商会日志
     * @param userId
     * @return
     * @throws BusinessException
     */
    public FixSizeLinkedList<HsIslandUnionLog> getUnionLogList(long userId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        return union.getUnionLogList();
    }

    /**
     * 获取个人日志
     * @param userId
     * @return
     * @throws BusinessException
     */
    public FixSizeLinkedList<HsIslandUserLog> getUserLogList(long userId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        return user.getUserLogList();
    }

    /**
     * 获取岛屿列表
     * @param userId
     * @return
     * @throws BusinessException
     */
    public Map<Integer, CrossHsIslandIsland> getIslandMap(long userId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        //获取海域
        CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
        if (floor == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
        }
        return floor.getIslandMap();
    }

    /************************************************战场相关****************************************************/

    /**
     * 进入战场(pve)
     *
     * @param userId 用户Id
     * @throws BusinessException
     */
    public void enterBattleField(long userId, int islandId, int x, int y) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        // 需要离开旧的战场
        long oldBattleFieldId = user.getUserData().getBattleFieldId();
        if (oldBattleFieldId != 0) {
            CrossHsIslandBattleField oldBattleField = getBattleField(oldBattleFieldId);
            // 离开战场
            if (oldBattleField != null) {
                oldBattleField.leaveBattleField(user);
            }
        }
        // 战场
        CrossHsIslandBattleField battleField = null;
        try {
            //加锁-商会，设置5秒超时
            if (!union.getLock().tryLock(5, TimeUnit.SECONDS)) {
                logger.error("海神岛-进入战场-加锁-超时：{}, {}, {}", userId, x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            //获取海域
            CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
            if (floor == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
            }
            //获取岛屿
            CrossHsIslandIsland island;
            if (islandId > 0) {
                island = floor.getIsland(islandId);
            } else {
                island = floor.getIsland(user.getUserData().getIslandId());
            }
            if (island == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_FOUND);
            }
            //判断事件是否完结
            if (island.checkPositionFinish(x, y)) {
                //同步一下地块信息
                floor.syncLaChangeForUser(userId, island.getIslandData().getIslandId(), x, y);
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_FINISHED);
            }
            //获取事件
            HsIslandEventData event = island.getEvent(x, y);
            if (event == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_FOUND);
            }
            //判断有没有怪物
            HsIslandMonsterData monsterData = event.getMonsterData();
            if (monsterData == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_MASTER_NOT_FOUND);
            }
            if (monsterData.isDead()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_MASTER_IS_DEAD);
            }
            // 获取怪物的战场
            if (monsterData.getBattleFieldId() == 0) {
                // 生成一个战场id
                monsterData.setBattleFieldId(maxBattleFieldId.incrementAndGet());
            }
            // 获取战场
            battleField = getBattleFieldNewIfNull(monsterData.getBattleFieldId(), ENEMY_MASTER, monsterData);
            //战场注入事件
            battleField.setEventData(event);
        } catch (InterruptedException e) {
            logger.error("海神岛-进入战场-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            union.getLock().unlock();
        }
        if (battleField == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BATTLE_FIELD_NOT_FOUND);
        }

        // 进入战场
        battleField.enterBattleField(user);

    }

    /**
     * 获取战场(战场不存在则创建)
     * @param battleFieldId 战场id
     * @param enemyType     敌人类型
     * @param monsterData   敌人数据
     */
    public CrossHsIslandBattleField getBattleFieldNewIfNull(long battleFieldId, HsIslandBattleFieldEnemyEnum enemyType, HsIslandMonsterData monsterData) throws BusinessException {
        if (!battleFieldMap.containsKey(battleFieldId)) {
            try {
                //加锁设置5秒超时
                if (!lock.tryLock(5, TimeUnit.SECONDS)) {
                    throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
                }
                if (!battleFieldMap.containsKey(battleFieldId)) {
                    // 创建新战场
                    CrossHsIslandBattleField battleField = new CrossHsIslandBattleField(
                            activityId,
                            groupId,
                            battleFieldId,
                            enemyType,
                            monsterData
                    );
                    battleFieldMap.put(battleField.getBattleFieldId(), battleField);
                }
            } catch (InterruptedException e) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            } finally {
                lock.unlock();
            }
        }
        return getBattleField(battleFieldId);
    }

    /**
     * 获取战场
     *
     * @param battleFieldId 战场id
     */
    public CrossHsIslandBattleField getBattleField(long battleFieldId) {
        return battleFieldMap.get(battleFieldId);
    }


    /**
     * 进入战场(boss，圣柱试炼)
     *
     * @param userId 用户Id
     * @throws BusinessException
     */
    public void enterBattleField(long userId, int bossId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        // 判断下boss出来了吗
        if (activityData.getBossData() == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BOSS_NOT_FOUND);
        }
        if (activityData.getBossData().isDead()) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BOSS_IS_DEAD);
        }
        // 传了bossId,顺便校验一下
        if (activityData.getBossData().getMonsterId() != bossId) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BOSS_NOT_FOUND);
        }
        // 需要离开旧的战场
        long oldBattleFieldId = user.getUserData().getBattleFieldId();
        if (oldBattleFieldId != 0) {
            CrossHsIslandBattleField oldBattleField = getBattleField(oldBattleFieldId);
            // 离开战场
            if (oldBattleField != null) {
                oldBattleField.leaveBattleField(user);
            }
        }
        // 获取boss战场，不存在则生成战场
        CrossHsIslandBattleField battleField = getBattleFieldNewIfNull(activityData.getBossData().getBattleFieldId(), ENEMY_BOSS, activityData.getBossData());

        if (battleField == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BATTLE_FIELD_NOT_FOUND);
        }

        // 进入战场
        battleField.enterBattleField(user);
    }


    /**
     * 离开战场
     *
     * @param userId 用户Id
     * @throws BusinessException
     */
    public void leaveBattleField(long userId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        long battleFieldId = user.getUserData().getBattleFieldId();
        if (battleFieldId == 0 || !battleFieldMap.containsKey(battleFieldId)) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BATTLE_FIELD_NOT_FOUND);
        }
        // 获取战场
        CrossHsIslandBattleField battleField = getBattleField(battleFieldId);
        if (battleField == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BATTLE_FIELD_NOT_FOUND);
        }
        // 离开战场
        battleField.leaveBattleField(user);
    }

    /**
     * PVE判断体力是否足够
     * @param user
     * @param eventData
     * @throws BusinessException
     */
    public int checkPveEnergyCost(CrossHsIslandUser user, HsIslandEventData eventData) throws BusinessException {
        //获取攻击次数
        HsIslandMonsterData monsterData = eventData.getMonsterData();

        int attTimes = 0;
        // 掉血数量大于0，拉一下伤害数据
        if (monsterData.getReBlood() > 0) {
            CrossHsIslandBattleFieldDamage battleFieldDamage = getBattleFieldDamageNewIfNull(monsterData.getBattleFieldId(), monsterData.getMonsterId(), ENEMY_MASTER);
            if (battleFieldDamage != null) {
                HsIslandBattleFieldDamageData damageData = battleFieldDamage.getDamageData(user.getUserData().getUserId());
                if (damageData != null) {
                    attTimes = damageData.getTimes();
                }
            }
        }

        if (user.getUserData().getUserId() == eventData.getUserId()) {
            //探索的体力
            int exploreCostEnergy = this.getConfig().getExploreEnergyCost(user.getUserData().getFloorId());
            //自己的怪，消耗体力（第一次攻击不消耗体力）
            int costEnergy = 0;
            if (attTimes > 0) {
                costEnergy = exploreCostEnergy + attTimes * this.config.HSISLAND_PVE_ENERGY_INCREASE;
            }
            //消耗体力
            if (costEnergy > 0) {
                boolean isEnergyEnough = user.reduceEnergy(costEnergy, HsIslandLogEnergyTypeEnum.COST_ATT);
                if (!isEnergyEnough) {
                    throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ENERGY_NOT_ENOUGH);
                }
            }
            return costEnergy;
        } else {
            //不是自己的怪，协助，消耗协助次数
            int costHelpNum = 1;
            boolean costHelpNumFlag = user.costHelpNum(costHelpNum);
            if (!costHelpNumFlag) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_HELP_NUM_NOT_ENOUGH);
            }
            return costHelpNum;
        }
    }

    /**
     * 战场操作-pve check
     * @param union
     * @param user
     * @param eventData
     * @throws BusinessException
     */
    public HsIslandPveCheckResult checkPveBattle(CrossHsIslandUnion union, CrossHsIslandUser user, HsIslandEventData eventData, List<Long> inviteUserIds) throws BusinessException {
        //事件是否存在
        if (eventData == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_FOUND);
        }
        //获取海域
        CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
        if (floor == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
        }
        //获取岛屿
        CrossHsIslandIsland island = floor.getIsland(eventData.getIslandId());
        if (island == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_FOUND);
        }
        //判断事件是否完结
        if (eventData.getFinishFlag() == HsIslandFinishFlagEnum.FINISH_YES.getType()) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_FINISHED);
        }
        //判断事件是PVE事件
        if (eventData.getEventId() != HsIslandEventIdEnum.EVENT_PVE.getType()
                && eventData.getEventId() != HsIslandEventIdEnum.EVENT_PVE_BIG.getType()) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_TYPE_ERROR);
        }
        if (eventData.getUserId() != user.getUserData().getUserId()) {
            //判断是否在pve保护时间
            long pveProtectTime = eventData.getCreateTime() + (long)this.getConfig().HSISLAND_PVE_PROTECT_TIME * 1000;
            if (System.currentTimeMillis() <= pveProtectTime) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_PVE_PROTECT_TIME);
            }
        }
        //获取怪配置
        HsIslandPveConfig pveConfig =this.config.getPveConfig(eventData.getMonsterData().getMonsterId());
        if (pveConfig == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_MONSTER_NOT_FOUND);
        }
        //获取邀请玩家
        List<CrossHsIslandUser> inviteUsers = new ArrayList<>();
        // 普通怪物可邀请协助
        if (inviteUserIds != null && !inviteUserIds.isEmpty()) {
            //判断邀请人数是否正确
            if (inviteUserIds.size() > pveConfig.getCanInviteNum()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_PVE_INVITE_NUM_ERROR);
            }
            for (long inviteUserId : inviteUserIds) {
                //不能邀请自己
                if (user.getUserData().getUserId() == inviteUserId) {
                    throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_INVITE_SELF);
                }
                //判断邀请的玩家是否是在商会里
                if (!union.getUserMap().containsKey(inviteUserId)) {
                    throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_INVITE_USER_NOT_IN_UNION);
                }
                CrossHsIslandUser inviteUser = this.getUser(inviteUserId);
                if (inviteUser != null) {
                    //判断邀请次数是否足够
                    if (inviteUser.getUserData().getCanPveInviteNum() <= 0) {
                        throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_PVE_INVITE_NOT_ENOUGH);
                    }
                    inviteUsers.add(inviteUser);
                }
            }
        }
        //扣除体力
        int costEnergy = this.checkPveEnergyCost(user, eventData);
        //返回
        HsIslandPveCheckResult result = new HsIslandPveCheckResult();
        result.setCostEnergy(costEnergy);
        result.setInviteUsers(inviteUsers);
        return result;
    }

    /**
     * 攻击怪物
     *
     * @param userId        用户id
     * @param inviteUserIds 邀请的用户列表（仅普通怪物可邀请）
     * @throws BusinessException
     */
    public HsIslandBattleOpResult attackMonster(long userId, List<Long> inviteUserIds) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        long battleFieldId = user.getUserData().getBattleFieldId();
        if (battleFieldId == 0 || !battleFieldMap.containsKey(battleFieldId)) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BATTLE_FIELD_NOT_FOUND);
        }
        // 获取战场
        CrossHsIslandBattleField battleField = getBattleField(battleFieldId);
        // 判断一下能不能打
        long canAttackTime = battleField.getMonsterData().getCreateTime();
        if (battleField.getEnemyType() == ENEMY_BOSS) {
            // boss有预告期
            canAttackTime = battleField.getMonsterData().getCreateTime() + this.config.HSISLAND_HOLY_PILLARS_NOTICE_TIME * DateHelper.SECOND_MILLIONS;
        }
        long nowTime = System.currentTimeMillis();
        if (nowTime < canAttackTime) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BATTLE_FIELD_IN_PRE_TIME);
        }
        if (battleField.getEnemyType() == ENEMY_BOSS) {
            // boss战判断下攻击间隔
            if (nowTime - user.getUserData().getLastAttackBossTime() < this.config.HSISLAND_ATTACK_CD.get(1) * DateHelper.SECOND_MILLIONS) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ATTACK_TIME_NO_ENOUGH);
            }
            // 自己处于调息状态无法攻击怪物
            if (user.isPvpRest()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ATTACK_IN_PVP_REST);
            }
        } else {
            // 普通战判断下攻击间隔
            if (nowTime - user.getUserData().getLastAttackMonsterTime() < this.config.HSISLAND_ATTACK_CD.get(0) * DateHelper.SECOND_MILLIONS) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ATTACK_TIME_NO_ENOUGH);
            }
        }
        HsIslandBattleOpResult opResult;
        try {
            //加锁-战场，设置5秒超时
            if (!battleField.getLock().tryLock(5, TimeUnit.SECONDS)) {
                logger.error("海神岛-攻击怪物-加锁-超时,用户id:{},战场id:{}", userId, battleField.getBattleFieldId());
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            // 判断下怪物的状态
            if (battleField.getMonsterData() == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_MONSTER_NOT_FOUND);
            }
            if (battleField.getMonsterData().isDead()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_MASTER_IS_DEAD);
            }
            //pve check
            int costEnergy = 0;
            List<CrossHsIslandUser> inviteUsers = new ArrayList<>();
            if (battleField.getEnemyType() == ENEMY_MASTER) {
                HsIslandPveCheckResult pveCheckResult = this.checkPveBattle(union, user, battleField.getEventData(), inviteUserIds);
                costEnergy = pveCheckResult.getCostEnergy();
                inviteUsers = pveCheckResult.getInviteUsers();
            }

            //获取下当前buff
            String buffs = user.getBuffStr();

            // 攻击怪物
            HsIslandBattleResult result = user.battleMonster(battleField, inviteUsers);

            // 处理结果
            opResult = handleAttackMonsterResult(user, result, battleField, inviteUserIds, costEnergy, buffs);
        } catch (InterruptedException e) {
            logger.error("海神岛-攻击怪物-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            battleField.getLock().unlock();
        }


        // 攻击同步
        battleField.addAttackMonsterResultMsg(
                HsIslandProto.HsIslandBattleFiledAttackResultMsg.newBuilder()
                        .setAttackType(1)
                        .setAttackUserId(userId)
                        .setAttackPvpEnergy(user.getPvpEnergy())
                        .setAttackDamage(opResult.getBattleResult().getDamage())
                        .setAttackTotalDamage(getTotalDamage(battleFieldId, userId))
                        .setAllBlood(battleField.getMonsterData().getAllBlood())
                        .setReBlood(battleField.getMonsterData().getReBlood())
                        .setAttackTime(nowTime)
                        .build()
        );

        if (battleField.getEnemyType() == ENEMY_BOSS) {
            // 圣柱试炼加个日志
            CrossAutoLogMgr.add(new LogCrossHsIslandBattle(
                    activityId,
                    groupId,
                    user.getUserData().getUnionId(),
                    user.getUserData().getUserId(),
                    battleField.getMonsterData().getMonsterId(),
                    opResult.getBattleResult().getDamage(),
                    battleField.getMonsterData().getBlood(),
                    opResult.getBattleResult().isWinFlag(),
                    0,
                    user.getPvpEnergy()
            ));
            //推送boss奖励红点
            if (opResult.getBattleResult().isWinFlag()) {
                CrossHsIslandBattleFieldDamage battleFieldDamage = getBattleFieldDamage(battleField.getBattleFieldId());
                if (battleFieldDamage != null) {
                    int rankNum = 0;
                    for (HsIslandRank rank : battleFieldDamage.getUnionDamageRankModel().getRankList()) {
                        rankNum++;
                        // 判断一下有没有奖励
                        Property bossReward = config.getBossReward(rankNum);
                        if (bossReward == null || bossReward.isNothing()) {
                            continue;
                        }
                        // 商会id
                        String unionId = rank.getRankId();
                        //推送红点
                        CrossHsIslandUnion rankUnion = this.getUnion(unionId);
                        if (rankUnion != null) {
                            for (CrossHsIslandUser rankUser : rankUnion.getUserMap().values()) {
                                rankUser.syncRedDotForBossReward();
                            }
                        }
                    }
                }
            }
        } else {
            if (opResult.getBattleResult().isWinFlag()) {
                //推送红点
                HsIslandEventData eventData = battleField.getEventData();
                if (eventData != null && eventData.getUserId() != userId) {
                    CrossHsIslandUser eventUser = this.getUser(eventData.getUserId());
                    eventUser.syncRedDot();
                }
            }
        }

        //返回
        return opResult;
    }


    public long getTotalDamage(long battleFieldId, long userId) {
        // 战场内伤害
        long myDamage = 0;
        CrossHsIslandBattleFieldDamage battleFieldDamage = getBattleFieldDamage(battleFieldId);
        if (battleFieldDamage != null) {
            HsIslandBattleFieldDamageData damageData = battleFieldDamage.getDamageData(userId);
            if (damageData != null) {
                myDamage = damageData.getTotalDamage();
            }
        }
        return myDamage;
    }


    /**
     * 处理攻击怪物结果
     */
    public HsIslandBattleOpResult handleAttackMonsterResult(CrossHsIslandUser user, HsIslandBattleResult battleResult, CrossHsIslandBattleField battleField, List<Long> inviteUserIds, int costEnergy, String buffs) {
        HsIslandBattleOpResult result = new HsIslandBattleOpResult();
        result.setBattleResult(battleResult);
        result.setBattleField(battleField);
        if (battleField.getEnemyType() == ENEMY_MASTER) {
            //PVE
            HsIslandEventData eventData = battleField.getEventData();
            HsIslandMonsterData monsterData = eventData.getMonsterData();
            //获取商会
            CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
            //获取海域
            CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
            //获取岛屿
            CrossHsIslandIsland island = floor.getIsland(eventData.getIslandId());
            //PVE
            Property reward = new Property();
            if (battleResult.isWinFlag()) {
                HsIslandPveConfig pveConfig = this.getConfig().getPveConfig(monsterData.getMonsterId());
                //事件注入击杀者ID
                eventData.setMonsterWinUserId(user.getUserData().getUserId());
                //自己的地块才有奖励
                if (user.getUserData().getUserId() == eventData.getUserId()) {
                    reward = PropertyHelper.parseNewStringToProperty(pveConfig.getReward());
                    eventData.setRewardFlag(HsIslandYnFlagEnum.YES.getType());
                } else {
                    //记录有奖励未领取（红点使用）
                    CrossHsIslandUser eventUser = this.getUser(eventData.getUserId());
                    if (eventUser != null && eventUser.getUserData().getFloorId() == eventData.getFloorId()) {
                        eventUser.addPveRewardNum(1);
                    }
                }
                //完结事件
                island.finishEvent(eventData);

                // 可以清理下战场
                needCleanBattleFieldIdSet.add(battleField.getBattleFieldId());
            }
            //获取的积分
            long addScore = user.getPveAddScore(monsterData, battleResult.getDamage());
            eventData.setUpdateOption();
            //奖励数据
            HsIslandReward hsIslandReward = user.createReward(addScore, reward, null, eventData);
            //添加积分
            user.addScore(hsIslandReward.getScore());
            //pve-日志
            this.addPveLog(user, union, battleResult, eventData, hsIslandReward);
            //同步地块数据变更
            if (user.getUserData().getUserId() == eventData.getUserId()) {
                floor.syncLaChange(island.getIslandData().getIslandId(), eventData, false);
            } else {
                floor.syncLaChange(island.getIslandData().getIslandId(), eventData, true);
            }
            //日志
            LogCrossHsIslandPve log = new LogCrossHsIslandPve(
                    user.getUserData().getActivityId(),
                    user.getUserData().getGroupId(),
                    user.getUserData().getUnionId(),
                    user.getUserData().getUserId(),
                    StringUtils.listToString(inviteUserIds, ","),
                    eventData.getEventId(),
                    eventData.getUserId(),
                    costEnergy,
                    union.getPowerAddRate(),
                    buffs,
                    battleResult.getDamage(),
                    hsIslandReward.getScore(),
                    PropertyHelper.parsePropertyToString(hsIslandReward.getReward()),
                    battleResult.isWinFlag() ? 1 : 0
            );
            CrossAutoLogMgr.add(log);
            //返回
            result.setReward(hsIslandReward);
            result.setEventData(eventData);
            return result;
        } else {
            // 圣柱试炼
            if (battleResult.isWinFlag()) {
                // 跑马灯
                syncMarqueeBossMsg(HsIslandMarqueeTypeEnum.MARQUEE_BOSS_DIE, activityData.getBossData().getMonsterId());
                // 成功击杀,增加boss击杀记录
                HsIslandKillBossRecord killBossRecord = new HsIslandKillBossRecord();
                killBossRecord.setActivityId(activityId);
                killBossRecord.setGroupId(groupId);
                killBossRecord.setMonsterId(battleField.getMonsterData().getMonsterId());
                killBossRecord.setBattleFieldId(battleField.getBattleFieldId());
                killBossRecord.setKillUserId(user.getUserData().getUserId());
                killBossRecord.setKillTime(System.currentTimeMillis());
                killBossRecord.setInsertOption();
                CrossHsIslandKillBossRecord crossHsIslandKillBossRecord = new CrossHsIslandKillBossRecord(killBossRecord);
                killBossRecordMap.put(killBossRecord.getBattleFieldId(), crossHsIslandKillBossRecord);

                // 推送一下
                for (CrossHsIslandUser crossHsIslandUser : userMap.values()) {
                    HsIslandProto.HsIslandKillBossSyncMsg.Builder syncMsg = HsIslandProto.HsIslandKillBossSyncMsg.newBuilder();
                    syncMsg.setActivityId(activityId);
                    HsIslandProto.HsIslandKillBossRecordTemp.Builder killBossRecordTemp = parseHsIslandKillBossRecordTemp(crossHsIslandKillBossRecord, crossHsIslandUser);
                    if (killBossRecordTemp != null) {
                        syncMsg.setKillBossRecord(killBossRecordTemp);
                    }
                    sendPacket(ClientProtocol.U_HS_ISLAND_BOSS_KILL_SYNC, syncMsg, crossHsIslandUser.getUserData().getUserId());
                }

            }
            return result;
        }
    }

    public  HsIslandProto.HsIslandKillBossRecordTemp.Builder parseHsIslandKillBossRecordTemp(CrossHsIslandKillBossRecord killBossRecord, CrossHsIslandUser user) {
        HsIslandProto.HsIslandKillBossRecordTemp.Builder killBossTemp = HsIslandProto.HsIslandKillBossRecordTemp.newBuilder();
        killBossTemp.setBattleFieldId(killBossRecord.getKillBossRecord().getBattleFieldId());
        killBossTemp.setMonsterId(killBossRecord.getKillBossRecord().getMonsterId());
        // 算下我商会的排名
        CrossHsIslandBattleFieldDamage myUnionBattleFieldDamage = getBattleFieldDamage(killBossRecord.getKillBossRecord().getBattleFieldId());
        int myUnionRank = -1;
        if (myUnionBattleFieldDamage != null) {
            CrossHsIslandRankListModel unionDamageRankModel = myUnionBattleFieldDamage.getUnionDamageRankModel();
            if (unionDamageRankModel != null) {
                myUnionRank = unionDamageRankModel.getMyRank(user.getUserData().getUnionId());
            }
            // 判断一下有没有奖励
            Property bossReward = config.getBossReward(myUnionRank);
            if (bossReward == null || bossReward.isNothing()) {
                myUnionRank = -1;
            }
        }
        killBossTemp.setMyUnionRank(myUnionRank);
        return killBossTemp;
    }

    /**
     * 攻击玩家
     *
     * @param userId       用户id
     * @param targetUserId 目标用户id
     */
    public void attackPlayer(long userId, long targetUserId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        long battleFieldId = user.getUserData().getBattleFieldId();
        if (battleFieldId == 0 || !battleFieldMap.containsKey(battleFieldId)) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BATTLE_FIELD_NOT_FOUND);
        }
        // 获取战场
        CrossHsIslandBattleField battleField = getBattleField(battleFieldId);
        // 判断一下能不能打
        long canAttackTime = battleField.getMonsterData().getCreateTime();
        if (battleField.getEnemyType() == ENEMY_BOSS) {
            // boss有预告期
            canAttackTime = battleField.getMonsterData().getCreateTime() + this.config.HSISLAND_HOLY_PILLARS_NOTICE_TIME * DateHelper.SECOND_MILLIONS;
        }
        long nowTime = System.currentTimeMillis();
        if (nowTime < canAttackTime) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BATTLE_FIELD_IN_PRE_TIME);
        }
        // 自己处于调息状态无法攻击他人
        if (user.isPvpRest()) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ATTACK_IN_PVP_REST);
        }
        // 判断下玩家攻击间隔
        if (nowTime - user.getUserData().getLastAttackPlayerTime() <  this.config.HSISLAND_ATTACK_CD.get(2) * DateHelper.SECOND_MILLIONS) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ATTACK_TIME_NO_ENOUGH);
        }

        CrossHsIslandUser targetBattleUser = null;

        // 我方扣除精力
        int myReducePvpEnergy = 0;
        // 敌方扣除精力
        int otherReducePvpEnergy = 0;
        try {
            //加锁-战场，设置5秒超时
            if (!battleField.getLock().tryLock(5, TimeUnit.SECONDS)) {
                logger.error("海神岛-攻击敌人-加锁-超时,用户id:{},战场id:{}", userId, battleField.getBattleFieldId());
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            // 获取敌对玩家的信息
            targetBattleUser = battleField.getBattleUser(targetUserId);
            if (targetBattleUser == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
            }
            if (targetBattleUser.isPvpRest()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ATTACK_IN_PVP_REST);
            }
            if (user.getUserData().getUnionId().equals(targetBattleUser.getUserData().getUnionId())) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ATTACK_IN_SAME_UNION);
            }
            // 判断下魂力限制只能攻击限制范围内的玩家
            if (!user.checkAttackPlayerPowerLimit(targetBattleUser.getPower())) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ATTACK_POWER_LIMIT);
            }
            
            // 只要有精力就能打,这里不用判断精力，只要不是调息状态都能打
            // 攻击敌人
            myReducePvpEnergy = this.config.HSISLAND_HOLY_PILLARS_FIGHT_CONSUME;
            //  B精力  （=rounddown(己方魂力/敌方魂力,1)*参数)
            otherReducePvpEnergy = Math.min(this.config.HSISLAND_HOLY_PILLARS_DECREASE_HP_MAX, BigDecimal.valueOf(user.getPower())
                    .divide(BigDecimal.valueOf(targetBattleUser.getPower()), 1, RoundingMode.DOWN)
                    .multiply(BigDecimal.valueOf(this.config.HSISLAND_HOLY_PILLARS_DECREASE_HP_PARAM))
                    .setScale(0, RoundingMode.DOWN).intValue());

            // 扣除精力
            user.reducePvpEnergy(myReducePvpEnergy);
            targetBattleUser.reducePvpEnergy(otherReducePvpEnergy);

            // 更新下当前的攻击时间
            user.getUserData().setLastAttackPlayerTime(nowTime);
        } catch (InterruptedException e) {
            logger.error("海神岛-攻击敌人-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            battleField.getLock().unlock();
        }
        // 攻击同步
        battleField.addAttackPlayerResultMsg(
                HsIslandProto.HsIslandBattleFiledAttackResultMsg.newBuilder()
                        .setAttackType(2)
                        .setAttackUserId(userId)
                        .setAttackPvpEnergy(user.getPvpEnergy())
                        .setAttackPvpEnergyLastTime(user.getUserData().getPvpEnergyLastTime())
                        .setAttackDamage(otherReducePvpEnergy)
                        .setAttackedUserId(targetUserId)
                        .setAttackedPvpEnergy(targetBattleUser.getPvpEnergy())
                        .setAttackedPvpEnergyLastTime(targetBattleUser.getUserData().getPvpEnergyLastTime())
                        .setAttackTime(nowTime)
                        .build()
        );
        // 回个包
        HsIslandProto.HsIslandBattleFieldOperateRespMsg.Builder respMsg = HsIslandProto.HsIslandBattleFieldOperateRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setType(2);
        // 我的个人信息
        respMsg.setMyUserData(CrossHsIslandActivityPb.buildHsIslandBattleFieldUserData(battleField, user));
        respMsg.setTargetUserData(CrossHsIslandActivityPb.buildHsIslandBattleFieldUserData(battleField, targetBattleUser));
        sendPacket(ClientProtocol.U_HS_ISLAND_BATTLE_FIELD_OPERATE, respMsg, userId);

        // 圣柱试炼加个日志
        CrossAutoLogMgr.add(new LogCrossHsIslandBattle(
                activityId,
                groupId,
                user.getUserData().getUnionId(),
                user.getUserData().getUserId(),
                targetUserId,
                otherReducePvpEnergy,
                targetBattleUser.getPvpEnergy(),
                targetBattleUser.isPvpRest(),
                myReducePvpEnergy,
                user.getPvpEnergy()
        ));
    }

    private ScheduledExecutorService debugExecutorService = null;

    /**
     * 测试指令
     */
    public void debugCode(HsIslandProto.HsIslandDebugReqMsg reqMsg, long userId) throws BusinessException {
        int channelId = ConfigHelper.getInt("channelId");
        if (!eChannelType.isInnerTestChannel(channelId)) {
            logger.error("GM指令仅限内网测试渠道,当前渠道不支持,渠道号:{}", channelId);
            return;
        }
        String code = reqMsg.getCode();
        String param = reqMsg.getParam();
        try {
            //获取玩家
            CrossHsIslandUser user = this.getUser(userId);
            if (user == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
            }
            //获取商会
            CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
            if (union == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
            }
            //获取海域
            CrossHsIslandFloor floor = union.getFloor(user.getUserData().getFloorId());
            if (floor == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_FLOOR_NOT_FOUND);
            }
            //获取岛屿
            CrossHsIslandIsland island = floor.getIsland(user.getUserData().getIslandId());
            if (island == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_ISLAND_NOT_FOUND);
            }
            if (code.equalsIgnoreCase("/hsd-test")) {
                sendDebugMessage(userId, String.format("海神岛指令测试,参数:%s", param));
            }
            if (code.equalsIgnoreCase("/hsd-finishEvent")) {
                int x = Integer.parseInt(param.split(",")[0]);
                int y = Integer.parseInt(param.split(",")[1]);
                //获取事件
                HsIslandEventData event = island.getEvent(x, y);
                if (event == null) {
                    throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_EVENT_NOT_FOUND);
                }
                //完结事件
                island.finishEvent(event);
            }
            if (code.equalsIgnoreCase("/hsd-addzy")) {
                addBattleValue(Long.parseLong(param));
                sendDebugMessage(userId, String.format("战意变更:%d,当前战意值:%d", Long.parseLong(param), activityData.getBattleValue()));
            }
            if (code.equalsIgnoreCase("/hsd-bossHp")) {
                long bossBlood = calcBossBlood();
                sendDebugMessage(userId, String.format("实时boss血量计算：%d", bossBlood));
            }
            if (code.equalsIgnoreCase("/hsd-npcmode")) {
                if (param.equals("1")) {
                    // 开多个线程同时并发跑
                    int core = 12;
                    debugExecutorService = ScheduledThreadPoolHelper.createGameScheduledThreadPoolExecutor(core, "海神岛-npc-");
                    for (int i = 0; i < core; i++) {
                        debugExecutorService.scheduleWithFixedDelay(new CrossHsIslandNpcActionTask(this, core, i), 0, 1000, TimeUnit.MILLISECONDS);
                    }
                    sendDebugMessage(userId, "NPC模式已开启");
                } else if (param.equals("2")) {
                    debugExecutorService.shutdown();
                    sendDebugMessage(userId, "NPC模式已关闭");
                }
            }
            if (code.equalsIgnoreCase("/hsd-addNpc")) {
                int npcNum = Integer.parseInt(param);
                for (int i = 0; i < npcNum; i++) {
                    // 生成npc
                    CrossUserBaseInfo npcUserBaseInfo = CrossNpcUserMgr.createCrossNpcUserBaseInfo();
                    //获取玩家数据
                    CrossHsIslandUser npc = this.getUser(npcUserBaseInfo.getUserId());
                    // 随机一个商会
                    CrossHsIslandUnion randomUnion = randomUnion();
                    if (randomUnion == null) {
                        continue;
                    }
                    npcUserBaseInfo.getUserBaseInfo().setUnionUid(randomUnion.getUnionData().getUnionId());
                    // 随机一组门客
                    List<HsIslandPatronsData> randomPatronsList = getRandomPatronsList();
                    if (npc == null) {
                        npc = this.initUser(npcUserBaseInfo.getUserId(), randomUnion, randomPatronsList);
                    }
                    //更新战力
                    npc.updatePower(randomPatronsList);

                    // 加点信息打印
                    UnionActivityGroupUnion groupUnion = Cross2UnionActivityGroupMgr.getUnionData(activityId, randomUnion.getUnionData().getUnionId(), groupId);

                    sendDebugMessage(npc.getUserData().getUserId(), String.format("新增npcId:%s,商会:%s;", npc.getUserData().getUserId(), groupUnion.getUnionBaseInfo().getUnionName()));
                }
            }
            if (code.equalsIgnoreCase("/hsd-czpvptl")) {
                user.resetPvpEnergy();
                sendDebugMessage(userId, String.format("重置精力成功,当前精力:%d", user.getUserData().getPvpEnergy()));
            }
            if (code.equalsIgnoreCase("/hsd-npcEnter")) {
                // 圣柱试炼npc全部进场
                // 获取当前boss
                HsIslandMonsterData bossData = activityData.getBossData();
                if (bossData != null && !bossData.isDead()) {
                    for (CrossHsIslandUser _user : userMap.values()) {
                        if (CrossNpcUserMgr.isNpc(_user.getUserData().getUserId())) {
                            enterBattleField(_user.getUserData().getUserId(), bossData.getMonsterId());
                        }
                    }
                    sendDebugMessage(userId, "圣柱试炼npc全部进场");
                } else {
                    sendDebugMessage(userId, "当前没有圣柱试炼");
                }
            }
            if (code.equalsIgnoreCase("/hsd-npcLeave")) {
                // 圣柱试炼npc全部退场
                for (CrossHsIslandUser _user : userMap.values()) {
                    if (CrossNpcUserMgr.isNpc(_user.getUserData().getUserId())) {
                        try {
                            leaveBattleField(_user.getUserData().getUserId());
                        } catch (BusinessException e) {

                        }
                    }
                }
                sendDebugMessage(userId, "圣柱试炼npc全部退场");
            }
            if (code.equalsIgnoreCase("/hsd-npcAction")) {
                npcAction = Integer.parseInt(param);
                if (param.equals("1")) {
                    sendDebugMessage(userId, "圣柱试炼npc全部攻击boss");
                } else if (param.equals("2")) {
                    sendDebugMessage(userId, "圣柱试炼npc随机攻击非本商会玩家");
                } else if (param.equals("3")) {
                    sendDebugMessage(userId, "圣柱试炼npc随机攻击所有目标");
                }
            }
            if (code.equalsIgnoreCase("/hsd-addBossHp")) {
                if (activityData.getBossData() != null && !activityData.getBossData().isDead()) {
                    activityData.getBossData().setAllBlood(activityData.getBossData().getAllBlood() + Long.parseLong(param));
                    sendDebugMessage(userId, String.format("boss增加血量:%s,当前血量:%s", param, activityData.getBossData().getBlood()));
                } else {
                    sendDebugMessage(userId, "boss不存在或者死了");
                }
            }
            if (code.equalsIgnoreCase("/hsd-enterNextFloor")) {
                union.updateMaxFloor();
                //获取目标海域
                CrossHsIslandFloor targetFloor = union.getFloor(union.getUnionData().getMaxFloorId());
                if (targetFloor == null) {
                    //创建海域
                    targetFloor = union.createFloor();
                }
                //玩家离开当前海域
                floor.removeUser(user);
                //玩家进入目标海域
                targetFloor.putUser(user);
                sendDebugMessage(userId, "进行一下个海域成功");
            }
            if (code.equalsIgnoreCase("/hsd-enterFloor")) {
                //获取目标海域
                CrossHsIslandFloor targetFloor = union.getFloor(Integer.parseInt(param));
                if (targetFloor != null) {
                    //玩家离开当前海域
                    floor.removeUser(user);
                    //玩家进入目标海域
                    targetFloor.putUser(user);
                    sendDebugMessage(userId, "进入海域成功");
                }
            }
            if (code.equalsIgnoreCase("/hsd-addKey")) {
                if (island.getIslandData().getKeyNum() <= 0) {
                    island.addKeyNum();
                }
                sendDebugMessage(userId, "添加海神之心成功");
            }
            if (code.equalsIgnoreCase("/hsd-bossSkipWaitTime")) {
                if (activityData.getBossData() != null && !activityData.getBossData().isDead()) {
                    activityData.getBossData().setCreateTime(0);
                    sendDebugMessage(userId, "boss跳过等待时间");
                } else {
                    sendDebugMessage(userId, "boss不存在或者死了");
                }
            }
            if (code.equalsIgnoreCase("/hsd-energy")) {
                user.getUserData().setEnergy(Integer.parseInt(param));
            }
            if (code.equalsIgnoreCase("/hsd-报一下魂力")) {
                for (CrossHsIslandUser islandUser : userMap.values()) {
                    sendDebugMessage(islandUser.getUserData().getUserId(), String.format("我的魂力:%s", islandUser.getPower()));
                }
            }
            if (code.equalsIgnoreCase("/hsd-事件统计")) {
                // 先保存下数据
                union.save();

                List<HsIslandEventData> eventList = new HsIslandEventDataDaoImpl().getHsIslandEventList(activityId, groupId, userId);
                Map<Integer, Integer> eventCntMap = new ConcurrentHashMap<>();
                for (HsIslandEventData eventData : eventList) {
                    if (eventData.getFinishFlag() == HsIslandFinishFlagEnum.FINISH_NOT.getType()) {
                        continue;
                    }
                    eventCntMap.put(eventData.getEventId(), eventCntMap.getOrDefault(eventData.getEventId(), 0) + 1);
                }
                StringBuffer stringBuffer = new StringBuffer();
                for (Map.Entry<Integer, Integer> entry : eventCntMap.entrySet()) {
                    stringBuffer.append(String.format("事件Id:%s,完成次数:%s;", entry.getKey(), entry.getValue()));
                }
                sendDebugMessage(userId, stringBuffer.toString());
            }
        } catch (Exception e) {
            sendDebugMessage(userId, String.format("指令异常，异常信息:%s", e));
        }
    }

    public CrossHsIslandUnion randomUnion() {
        ArrayList<CrossHsIslandUnion> unionList = new ArrayList<>(unionMap.values());
        return unionList.get(randomHelper.next(0, unionList.size()));
    }


    /**
     * 随机复制一份门客数据
     * @return
     */
    public List<HsIslandPatronsData> getRandomPatronsList() {
        List<HsIslandPatronsData> result = new ArrayList<>();
        // 从已有的用户中随机挑一组门客吧，测试用
        List<Long> list = new ArrayList<>();
        for (CrossHsIslandUser user : userMap.values()) {
            if (CrossNpcUserMgr.isNpc(user.getUserData().getUserId())) {
                continue;
            }
            list.add(user.getUserData().getUserId());
        }
        if (list.size() == 0) {
            logger.error("占无可用门客");
            return new ArrayList<>();
        }
        Long userId = list.get(randomHelper.next(0, list.size()));
        CrossHsIslandUser user = getUser(userId);
        for (HsIslandPatronsData patronsData : user.getUserData().getPatronsMap().values()) {
            result.add(patronsData.clone());
        }
        return result;
    }

    /**
     * 发送聊天信息-调试用
     *
     * @param userId
     * @param content
     */
    public void sendDebugMessage(long userId, String content) {
        int channelId = ConfigHelper.getInt("channelId");
        if (!eChannelType.isInnerTestChannel(channelId)) {
            return;
        }
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if (userBaseInfo == null) {
            return;
        }
        // 封装下聊天内容
        WorldMessageProto.WorldMessageTempMsg.Builder msg = WorldMessageMgr.parseWorldMessageTempMsg(
                userBaseInfo,
                userId,
                eMessageType.CrossActivityChat.getValue(),
                eChatContentType.Common.getContentType(),
                content,
                DateHelper.getCurrentTime(),
                activityId,
                ""
        );
        ActivityChatMgr.activityChat(activityId, msg.build());
    }


    public void debugTask() {
        logger.debug("测试任务,活动id:{}", activityId);
    }

    /**
     * 圣柱试炼定时任务
     * 定时增加战意值、检测boss是否出现
     */
    public void bossTask() throws BusinessException {

        this.commonCheck(0, true, true);

        // 当前战意值
        long zeroTimeStamp = DateHelper.getTodayZeroTimeStamp();
        // 上次恢复战意值的时间(最早为每日活动开始时间)
        long lastBattleValueTime = Math.max(zeroTimeStamp + this.config.HSISLAND_OPEN_TIME_OF_EACH_DAY * DateHelper.HOUR_MILLIONS, activityData.getLastBattleValueTime());
        // 当前时间
        long nowTime = Math.min(zeroTimeStamp + this.config.HSISLAND_END_TIME_OF_EACH_DAY * DateHelper.HOUR_MILLIONS, System.currentTimeMillis());
        // 恢复间隔
        long recovery = this.config.HSISLAND_HOLY_PILLARS_ADD_PROGRESS.get(0) * DateHelper.SECOND_MILLIONS;
        // 间隔了多少次
        long offsetTimes = (nowTime - lastBattleValueTime) / recovery;
        if (offsetTimes > 0) {
            // 增加了多少战意值,最大只能积累一条
            long addValue = offsetTimes * this.config.HSISLAND_HOLY_PILLARS_ADD_PROGRESS.get(1);
            // 更新一下时间
            activityData.setLastBattleValueTime(lastBattleValueTime + offsetTimes * recovery);
            // 增加战意值
            addBattleValue(addValue);
        }

        // 战意变更需要检测boss出来没有
        boolean createBoss = checkBoss();

        if (createBoss) {
            // 跑马灯
            syncMarqueeBossMsg(HsIslandMarqueeTypeEnum.MARQUEE_BOSS, activityData.getBossData().getMonsterId());
            // 圣柱创建战斗后,重置所有人的精力值
            for (CrossHsIslandUser user : userMap.values()) {
                user.resetPvpEnergy();
            }
        }

        // 同步一下所有活人
        syncBattleValue();

        if (createBoss) {
            // 创建boss时加个日志
            CrossAutoLogMgr.add(new LogCrossHsIslandBoss(
                    activityId,
                    groupId,
                    activityData.getMaxBattleValue(),
                    activityData.getBattleValue(),
                    activityData.getBossData().getMonsterId(),
                    activityData.getBossData().getBlood(),
                    activityData.getBossData().getBattleFieldId()
            ));
        }
    }

    /**
     * 战意同步
     */
    public void syncBattleValue() {
        HsIslandProto.HsIslandBattleValueSyncMsg.Builder syncMsg = HsIslandProto.HsIslandBattleValueSyncMsg.newBuilder();
        syncMsg.setActivityId(activityId);
        if (activityData.getBossData() != null) {
            syncMsg.setBossData(CrossHsIslandActivityPb.buildHsIslandMonsterData(activityId, groupId, activityData.getBossData(), false));
        }
        syncMsg.setBattleValue(activityData.getBattleValue());
        syncMsg.setMaxBattleValue(activityData.getMaxBattleValue());
        syncMsg.setBossNum(activityData.getBossNum());
        sendPacketToAll(ClientProtocol.U_HS_ISLAND_SYNC_BOSS_DATA, syncMsg, userMap.keySet());
    }

    /**
     * 战场同步任务
     */
    public void syncBattleFieldTask() throws BusinessException {
        this.commonCheck(0, true, true);
        for (CrossHsIslandBattleField battleField : battleFieldMap.values()) {
            // 进入战场同步
            battleField.syncEnterBattleField();
            // 操作同步
            battleField.syncBattleFieldAttack();
            // 离开战场同步
            battleField.syncLeaveBattleField();
        }
    }

    /**
     * 检测boss
     * @return 是否出现boss
     */
    private boolean checkBoss() {
        if (activityData.getMaxBattleValue() == 0) {
            logger.error("boss战意值异常,战意值为0,活动id:{}", this::getActivityId);
        }
        if (activityData.getBattleValue() < activityData.getMaxBattleValue()) {
            // 没达到战意值，先不处理了
            return false;
        }
        try {
            //加锁-检测boss，设置5秒超时
            if (!this.lock.tryLock(5, TimeUnit.SECONDS)) {
                logger.error("海神岛-检测boss-加锁-超时：{}", activityId);
                return false;
            }
            // 当前boss死没死，没死也不处理
            if (activityData.getBossData() != null && !activityData.getBossData().isDead()) {
                return false;
            }
            // 拿到下一个bossId
            HsIslandMonsterData bossData = createPveMonster(this.config.getNextBossId(activityData.getBossNum()));
            activityData.setBossData(bossData);
            activityData.setBossNum(activityData.getBossNum() + 1);
            // 扣掉战意值
            activityData.setBattleValue(activityData.getBattleValue() - activityData.getMaxBattleValue());
            return true;
        } catch (InterruptedException e) {
            logger.error("海神岛-检测boss-tryLock报错：{}", e);
        } finally {
            this.lock.unlock();
        }
        return false;
    }

    /**
     * 增加战意值
     *
     * @param addValue 增加值
     */
    public void addBattleValue(long addValue) {
        if (addValue == 0) {
            return;
        }

        activityData.setBattleValue(Math.min(activityData.getMaxBattleValue(), activityData.getBattleValue() + addValue));

        logger.debug("活动id:{},增加战意值:{},当前战意值:{},战意值上限:{}", activityId, addValue, activityData.getBattleValue(), activityData.getMaxBattleValue());
    }

    /**
     * npc行为
     */
    private int npcAction = 0;

    /**
     * npc 操作定时任务
     */
    public void npcActionTask(int total, int taskIndex) throws BusinessException {
        this.commonCheck(0, true, true);
        int channelId = ConfigHelper.getInt("channelId");
        if (!eChannelType.isInnerTestChannel(channelId)) {
            return;
        }
        if (npcAction == 0) {
            return;
        }
        long nowTime = System.currentTimeMillis();
        for (CrossHsIslandUser npc : userMap.values()) {
            long npcId = npc.getUserData().getUserId();
            if (!CrossNpcUserMgr.isNpc(npcId)) {
                continue;
            }
            if (npcId % total != taskIndex) {
                continue;
            }
            CrossHsIslandBattleField battleField = getBattleField(npc.getUserData().getBattleFieldId());
            if (battleField == null || battleField.getEnemyType() != ENEMY_BOSS) {
                continue;
            }
            if (battleField.getMonsterData().isDead()) {
                continue;
            }
            if (npc.isPvpRest()) {
                continue;
            }

            // 判断一下能不能打
            long canAttackTime = battleField.getMonsterData().getCreateTime() + this.config.HSISLAND_HOLY_PILLARS_NOTICE_TIME * DateHelper.SECOND_MILLIONS;
            if (nowTime < canAttackTime) {
                continue;
            }
            // 随机一个攻击时间，让npc错开攻击时间
//            long randomAttackTime = randomHelper.next(0, 1000);
            long randomAttackTime = 0;

            boolean attackMonster = false;
            if (npcAction == 1) {
                attackMonster = true;
            } else if (npcAction == 2) {
                attackMonster = false;
            } else if (npcAction == 3) {
                attackMonster = randomHelper.next(0, 100) < 80;
            } else {
                continue;
            }

            if (attackMonster) {
                // 攻击boss
                if (nowTime - (npc.getUserData().getLastAttackMonsterTime() + randomAttackTime) > this.config.HSISLAND_ATTACK_CD.get(1) * DateHelper.SECOND_MILLIONS) {
                    attackMonster(npcId, new ArrayList<>());
                }
            } else {
                // 随机敌人
                if (nowTime - (npc.getUserData().getLastAttackPlayerTime() + randomAttackTime) > this.config.HSISLAND_ATTACK_CD.get(2) * DateHelper.SECOND_MILLIONS) {
                    long randomEnemyUserId = battleField.getRandomEnemyUserId(npc);
                    if (randomEnemyUserId != 0) {
                        attackPlayer(npcId, randomEnemyUserId);
                    }
                }
            }
        }
    }

    /**
     * 获取战场伤害
     *
     * @param battleFieldId
     */
    public CrossHsIslandBattleFieldDamage getBattleFieldDamageNewIfNull(long battleFieldId, int monsterId, HsIslandBattleFieldEnemyEnum enemyType) throws BusinessException {
        if (!battleFieldDamageMap.containsKey(battleFieldId)) {
            CrossHsIslandBattleFieldDamage data = new CrossHsIslandBattleFieldDamage(activityId, groupId, battleFieldId, monsterId, enemyType);
            battleFieldDamageMap.put(data.getBattleFieldId(), data);
        }
        return getBattleFieldDamage(battleFieldId);
    }

    /**
     * 获取战场商会榜单
     *
     * @param battleFieldId
     */
    public CrossHsIslandBattleFieldDamage getBattleFieldDamage(long battleFieldId) {
        return battleFieldDamageMap.get(battleFieldId);
    }

    /**
     * 待清理的战场信息
     */
    private Set<Long> needCleanBattleFieldIdSet = new ConcurrentHashSet<>();

    /**
     * 添加待清理的战场
     * @param battleFieldId
     */
    public void addNeedCleanBattleFieldId(long battleFieldId) {
        this.needCleanBattleFieldIdSet.add(battleFieldId);
    }

    /**
     * 战场清理定时任务
     */
    public void battleFieldCleanTask() {
        if (needCleanBattleFieldIdSet.isEmpty()) {
            return;
        }
        List<Long> battleFieldIdList = new ArrayList<>(needCleanBattleFieldIdSet);

        Set<Long> canCleanBattleFieldIdSet = new ConcurrentHashSet<>();
        for (Long battleFieldId : battleFieldIdList) {
            CrossHsIslandBattleField battleField = getBattleField(battleFieldId);
            if (battleField == null || battleField.getEnemyType() == ENEMY_BOSS) {
                // 圣柱试炼先不清理
                continue;
            }
            // 没同步完先不处理
            if (!battleField.getSyncEnterUserIdSet().isEmpty() || !battleField.getSyncLeaveUserIdSet().isEmpty()) {
                continue;
            }
            boolean canClean = true;
            // 战场伤害数据有没有都入库了
            CrossHsIslandBattleFieldDamage battleFieldDamage = getBattleFieldDamage(battleFieldId);
            if (battleFieldDamage != null) {
                for (HsIslandBattleFieldDamageData damageData : battleFieldDamage.getDamageDataMap().values()) {
                    if (damageData.isDirty()) {
                        canClean = false;
                    }
                }
            }
            if (canClean) {
                canCleanBattleFieldIdSet.add(battleFieldId);
            }
        }
        for (Long battleFieldId : canCleanBattleFieldIdSet) {
            needCleanBattleFieldIdSet.remove(battleFieldId);
            battleFieldMap.remove(battleFieldId);
            battleFieldDamageMap.remove(battleFieldId);
            logger.debug("战场清理成功,活动id:{},战场id:{}", activityId, battleFieldId);
        }
    }

    /**
     * 获取战场信息
     * @param userId
     * @throws BusinessException
     */
    public void battleFieldDataReq(long userId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(user.getUserData().getUnionId());
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        CrossHsIslandBattleField battleField = getBattleField(user.getUserData().getBattleFieldId());
        if (battleField == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BATTLE_FIELD_NOT_FOUND);
        }

        HsIslandProto.HsIslandBattleFieldDataRespMsg.Builder respMsg = HsIslandProto.HsIslandBattleFieldDataRespMsg.newBuilder();
        respMsg.setRet(0);
        // 从战场pb拿信息
        HsIslandProto.HsIslandBattleFieldDataMsg.Builder battleFieldMsg = CrossHsIslandActivityPb.builderHsIslandBattleFieldData(battleField);
        respMsg.addAllUserData(battleFieldMsg.getUserDataList());
        respMsg.addAllUnionData(battleFieldMsg.getUnionDataList());
        respMsg.setMonsterData(CrossHsIslandActivityPb.buildHsIslandMonsterData(activityId, groupId, battleField.getMonsterData(), true));
        sendPacket(ClientProtocol.U_HS_ISLAND_BATTLE_FIELD_DATA_REQ, respMsg, userId);
    }

    /**
     * 获取战场商会玩家LIST
     * @param userId
     * @param battleFieldId
     * @param unionId
     * @throws BusinessException
     */
    public void getBattleFieldUnionUserList(long userId, long battleFieldId, String unionId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, true, true);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        //获取商会
        CrossHsIslandUnion union = this.getUnion(unionId);
        if (union == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_UNION_NOT_FOUND);
        }
        CrossHsIslandBattleField battleField = getBattleField(battleFieldId);
        if (battleField == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BATTLE_FIELD_NOT_FOUND);
        }
        //遍历战场玩家，构造PB
        HsIslandProto.HsIslandBattleFieldUnionUserListRespMsg.Builder respMsg = HsIslandProto.HsIslandBattleFieldUnionUserListRespMsg.newBuilder();
        respMsg.setRet(0);
        CrossHsIslandBattleFieldDamage fieldDamage = getBattleFieldDamage(battleFieldId);
        for (HsIslandBattleFieldDamageData damageData : fieldDamage.getDamageDataMap().values()) {
            if (Objects.equals(damageData.getUnionId(), unionId)) {
                HsIslandProto.HsIslandBattleFieldUserDataMsg.Builder userTemp = HsIslandProto.HsIslandBattleFieldUserDataMsg.newBuilder();
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(damageData.getUserId());
                if (userBaseInfo == null) {
                    continue;
                }
                userTemp.setUserId(damageData.getUserId());
                userTemp.setPlayerData(PlayerBasePb.parsePlayerSimpleBaseTempMsg(userBaseInfo));
                userTemp.setDamage(damageData.getTotalDamage());
                respMsg.addUsers(userTemp);
            }
        }
        sendPacket(ClientProtocol.U_HS_ISLAND_GET_BATTLE_FIELD_UNION_USER_LIST, respMsg, userId);
    }

    /**
     * 领取boss伤害排行奖励
     *
     * @param userId
     * @param battleFieldId
     */
    public void getKillBossDamageRankReward(long userId, long battleFieldId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, false, false);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        synchronized (user) {
            // 判断是否领奖了
            if (user.getUserData().getHadRewardBattleFieldIdList().contains(battleFieldId)) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BOSS_HAD_REWARD);
            }
            // 如果boss还没死也不让领
            CrossHsIslandKillBossRecord killBossRecord = killBossRecordMap.get(battleFieldId);
            if (killBossRecord == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BOSS_NO_DEAD);
            }
            // 获取boss排行榜单
            CrossHsIslandBattleFieldDamage battleFieldDamage = getBattleFieldDamageNewIfNull(battleFieldId, killBossRecord.getKillBossRecord().getMonsterId(), ENEMY_BOSS);
            if (battleFieldDamage == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BOSS_NO_RANK);
            }
            CrossHsIslandRankListModel unionDamageRankModel = battleFieldDamage.getUnionDamageRankModel();
            if (unionDamageRankModel == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BOSS_NO_RANK);
            }
            // 我商会的排名
            int myRank = unionDamageRankModel.getMyRank(user.getUserData().getUnionId());
            if (myRank == -1) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BOSS_RANK_LIMIT);
            }
            // 领奖
            Property bossReward = this.config.getBossReward(myRank);
            if (bossReward == null || bossReward.isNothing()) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BOSS_RANK_LIMIT);
            }
            // 标识下领奖状态
            user.getUserData().getHadRewardBattleFieldIdList().add(battleFieldId);
            user.getUserData().setUpdateOption();

            // 发到游戏服领奖
            HsIslandProto.HsIslandKillBossDamageRankRewardFromCrossMsg.Builder crossMsg = HsIslandProto.HsIslandKillBossDamageRankRewardFromCrossMsg.newBuilder();
            crossMsg.setRet(0);
            crossMsg.setReward(PropertyHelper.parsePropertyToString(bossReward));
            crossMsg.addAllHadRewardBattleFieldIdList(user.getUserData().getHadRewardBattleFieldIdList());
            sendPacket(GameProtocol.S_HS_ISLAND_KILL_BOSS_DAMAGE_RANK_REWARD_FROM_CROSS, crossMsg, userId);
        }
    }

    /**
     * 拉一下boss伤害榜单
     *
     * @param userId 用户id
     * @throws BusinessException
     */
    public void getKillBossDamageRankList(long userId,long battleFieldId) throws BusinessException {
        //通用检测
        this.commonCheck(userId, false, false);
        //获取玩家
        CrossHsIslandUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_USER_NOT_FOUND);
        }
        long killUserId = 0;
        int bossId = 0;
        // 先判断下是不是当前的boss
        if (activityData.getBossData() != null && !activityData.getBossData().isDead() && activityData.getBossData().getBattleFieldId() == battleFieldId) {
            bossId = activityData.getBossData().getMonsterId();
        } else {
            CrossHsIslandKillBossRecord killBossRecord = killBossRecordMap.get(battleFieldId);
            if (killBossRecord == null) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_BOSS_NO_DEAD);
            }
            killUserId = killBossRecord.getKillBossRecord().getKillUserId();
            bossId = killBossRecord.getKillBossRecord().getMonsterId();
        }
        HsIslandProto.HsIslandKillBossDamageRankRespMsg.Builder respMsg = HsIslandProto.HsIslandKillBossDamageRankRespMsg.newBuilder();
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(killUserId);
        if (userBaseInfo != null) {
            respMsg.setKillUser(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
        }
        // 获取伤害榜单
        CrossHsIslandBattleFieldDamage battleFieldDamage = getBattleFieldDamageNewIfNull(battleFieldId, bossId, ENEMY_BOSS);
        if (battleFieldDamage != null && battleFieldDamage.getUnionDamageRankModel() != null) {
            CrossHsIslandRankListModel unionDamageRankModel = battleFieldDamage.getUnionDamageRankModel();
            int rankNum = 0;
            for (HsIslandRank rank : unionDamageRankModel.getRankList()) {
                rankNum++;
                // 领奖
                Property bossReward = this.config.getBossReward(rankNum);
                if (bossReward == null || bossReward.isNothing()) {
                    // 没奖励就不在列表显示了
                    continue;
                }
                String unionId = rank.getRankId();
                HsIslandProto.HsIslandBattleFieldUnionDataMsg.Builder unionTemp = HsIslandProto.HsIslandBattleFieldUnionDataMsg.newBuilder();
                unionTemp.setUnionUid(unionId);
                UnionActivityGroupUnion groupUnion = Cross2UnionActivityGroupMgr.getUnionData(activityId, unionId, groupId);
                if (groupUnion != null) {
                    unionTemp.setUnionInfo(UnionBasePb.parseUnionBaseTempMsg(groupUnion.getUnionBaseInfo()));
                }
                unionTemp.setRank(rankNum);
                unionTemp.setDamage(rank.getValue());
                respMsg.addUnionData(unionTemp);
            }
        }
        respMsg.setRet(0);
        sendPacket(ClientProtocol.U_HS_ISLAND_KILL_BOSS_DAMAGE_RANK_REQ, respMsg, userId);
    }


    public Map<Long, CrossHsIslandKillBossRecord> getKillBossRecordMap() {
        return killBossRecordMap;
    }

    public void sendRewardTask() throws BusinessException {
        // 活动结束才能发
        if (System.currentTimeMillis() / 1000 < config.getActivityInfo().getEndTime()) {
            // 时间没到
            return;
        }
        // 判断下有没有补发过
        if (activityData.isSendReward()) {
            return;
        }
        try {
            //加锁设置5秒超时
            if (!lock.tryLock(5, TimeUnit.SECONDS)) {
                throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
            }
            // 锁里再判断下
            if (activityData.isSendReward()) {
                return;
            }
            // 先设置补发标识
            activityData.setSendReward(true);

            // 开始补发圣柱奖励
            sendUnionDamageRankReward();
        } catch (InterruptedException e) {
            throw BusinessException.newException(GameErrorCode.E_HS_ISLAND_REQUEST_TIME_OUT);
        } finally {
            lock.unlock();
        }
    }


    /**
     * 商会伤害奖励榜单补发
     */
    private void sendUnionDamageRankReward() throws BusinessException {

        Map<Long, Property> rewardMap = new ConcurrentHashMap<>();

        for (CrossHsIslandUser user : userMap.values()) {
            for (CrossHsIslandKillBossRecord killBossRecord : killBossRecordMap.values()) {
                if (user.getUserData().getHadRewardBattleFieldIdList().contains(killBossRecord.getKillBossRecord().getBattleFieldId())) {
                    // 已领过不处理
                    continue;
                }
                // 获取boss排行榜单
                CrossHsIslandBattleFieldDamage battleFieldDamage = getBattleFieldDamageNewIfNull(killBossRecord.getKillBossRecord().getBattleFieldId(), killBossRecord.getKillBossRecord().getMonsterId(), ENEMY_BOSS);
                if (battleFieldDamage == null) {
                    continue;
                }
                CrossHsIslandRankListModel unionDamageRankModel = battleFieldDamage.getUnionDamageRankModel();
                if (unionDamageRankModel == null) {
                    continue;
                }
                // 我商会的排名
                int myRank = unionDamageRankModel.getMyRank(user.getUserData().getUnionId());
                if (myRank == -1) {
                    continue;
                }
                // 领奖
                Property bossReward = this.config.getBossReward(myRank);
                if (bossReward == null || bossReward.isNothing()) {
                    continue;
                }
                // 加到领奖列表里
                Property reward = rewardMap.getOrDefault(user.getUserData().getUserId(), new Property());
                reward.addProperty(bossReward);
                rewardMap.put(user.getUserData().getUserId(), reward);

                // 标识下领奖状态
                user.getUserData().getHadRewardBattleFieldIdList().add(killBossRecord.getKillBossRecord().getBattleFieldId());
            }
        }

        // 发到游戏服
        if (!rewardMap.isEmpty()) {
            for (Map.Entry<Long, Property> entry : rewardMap.entrySet()) {
                sendPacket(GameProtocol.S_HS_ISLAND_KILL_BOSS_DAMAGE_RANK_MAIL_REWARD,
                        HsIslandProto.HsIslandKillBossDamageRankMailRewardMsg.newBuilder()
                                .setUserId(entry.getKey())
                                .setReward(PropertyHelper.parsePropertyToString(entry.getValue())),
                        entry.getKey()
                );
            }
        }
    }

    public void fixBug(String param) {
        // 预留一个方法
    }
}
